Storing multiple Justifications per block (#7640)

* primitives/runtime: initial changes on supporting multiple Justifications

* primitives/runtime: make Justifications strongly typed

* Encode/decode Justifications

* primitives/runtime: add Justification type

* backend: apply_finality and finalize_block takes a single Justification

* manual-seal: create engine id and let rpc take encoded justification

* backend: skeleton functions for appending justifications

* backend: initial implementation append_justification

Initial implementation of append_justification on the Backend trait, and also remove unused skeleton
functions for append_justificaton on Finaziler trait.
k

* backend: guard against duplicate consensus engine id

* client/db: add check for block finality

* client/api: add append_justification to in_mem db

* client/light: add no-op append_justification

* network: fix decode call for Justification

* network: only send a single Justification in BlockData

* network: minor comment update

* protocol: update field names to distinguish single justification

* client: further field renames to plural

* client: update function names to plural justifications

* client/db: upgrade existing database for new format

* network: remove dependency on grandpa crate

* db: fix check for finalized block

* grandpa: check for multiple grandpa justifications hwne importing

* backend: update Finalizer trait to take multiple Justifications

* db: remove debugging statements in migration code

* manual-seal: update note about engine id

* db: fix check for finalized block

* client: update variable name to reflect it is now plural

* grandpa: fix incorrect empty Justications in test

* primitives: make Justifications opaque to avoid being empty

* network: fix detecting empty Justification

* runtime: doc strings for Justifications functions

* runtime: add into_justifications

* primitives: check for duplicates in when adding to Justifications

* network/test: use real grandpa engine id in test

* client: fix reviewer comments

* primitives: rename Justifications::push to append

* backend: revert changes to Finalizer trait

* backend: revert mark_finalized

* backend: revert changes to finalize_block

* backend: revert finalized_blocks

* db: add a quick early return for performance

* client: minor reviewer comments

* service/test: use local ConsensusEngineId

* network: add link to issue for sending multiple Justifications

* Apply suggestions from code review

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* Apply suggestions from code review

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* network: tweaks to review suggestions

* network: revert change to BlockData for backwards compatibility

* Apply suggestion from code review

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>

* Apply suggestions from code review

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

* primitives: update doc comment for Justifications

* client/db/upgrade: avoid grandpa crate dependency

* consensus: revert to single Justification for import_justification

* primitives: improve justifications docs

* style cleanups

* use and_then

* client: rename JUSTIFICATIONS db column

* network: revert to using FRNK in network-test

Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com>
Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Jon Häggblad
2021-03-17 22:18:16 +01:00
committed by GitHub
parent c7d32ba9a6
commit 0d6884b919
43 changed files with 635 additions and 270 deletions
+47 -16
View File
@@ -22,6 +22,7 @@ use futures::{Future, executor::block_on};
use super::*;
use sp_consensus::block_validation::Validation;
use substrate_test_runtime::Header;
use sp_runtime::Justifications;
fn test_ancestor_search_when_common_is(n: usize) {
sp_tracing::try_init_simple();
@@ -248,13 +249,14 @@ fn sync_justifications() {
net.block_until_sync();
// there's currently no justification for block #10
assert_eq!(net.peer(0).client().justification(&BlockId::Number(10)).unwrap(), None);
assert_eq!(net.peer(1).client().justification(&BlockId::Number(10)).unwrap(), None);
assert_eq!(net.peer(0).client().justifications(&BlockId::Number(10)).unwrap(), None);
assert_eq!(net.peer(1).client().justifications(&BlockId::Number(10)).unwrap(), None);
// we finalize block #10, #15 and #20 for peer 0 with a justification
net.peer(0).client().finalize_block(BlockId::Number(10), Some(Vec::new()), true).unwrap();
net.peer(0).client().finalize_block(BlockId::Number(15), Some(Vec::new()), true).unwrap();
net.peer(0).client().finalize_block(BlockId::Number(20), Some(Vec::new()), true).unwrap();
let just = (*b"FRNK", Vec::new());
net.peer(0).client().finalize_block(BlockId::Number(10), Some(just.clone()), true).unwrap();
net.peer(0).client().finalize_block(BlockId::Number(15), Some(just.clone()), true).unwrap();
net.peer(0).client().finalize_block(BlockId::Number(20), Some(just.clone()), true).unwrap();
let h1 = net.peer(1).client().header(&BlockId::Number(10)).unwrap().unwrap();
let h2 = net.peer(1).client().header(&BlockId::Number(15)).unwrap().unwrap();
@@ -269,10 +271,20 @@ fn sync_justifications() {
net.poll(cx);
for height in (10..21).step_by(5) {
if net.peer(0).client().justification(&BlockId::Number(height)).unwrap() != Some(Vec::new()) {
if net
.peer(0)
.client()
.justifications(&BlockId::Number(height))
.unwrap() != Some(Justifications::from((*b"FRNK", Vec::new())))
{
return Poll::Pending;
}
if net.peer(1).client().justification(&BlockId::Number(height)).unwrap() != Some(Vec::new()) {
if net
.peer(1)
.client()
.justifications(&BlockId::Number(height))
.unwrap() != Some(Justifications::from((*b"FRNK", Vec::new())))
{
return Poll::Pending;
}
}
@@ -295,7 +307,8 @@ fn sync_justifications_across_forks() {
// for both and finalize the small fork instead.
net.block_until_sync();
net.peer(0).client().finalize_block(BlockId::Hash(f1_best), Some(Vec::new()), true).unwrap();
let just = (*b"FRNK", Vec::new());
net.peer(0).client().finalize_block(BlockId::Hash(f1_best), Some(just), true).unwrap();
net.peer(1).request_justification(&f1_best, 10);
net.peer(1).request_justification(&f2_best, 11);
@@ -303,8 +316,16 @@ fn sync_justifications_across_forks() {
block_on(futures::future::poll_fn::<(), _>(|cx| {
net.poll(cx);
if net.peer(0).client().justification(&BlockId::Number(10)).unwrap() == Some(Vec::new()) &&
net.peer(1).client().justification(&BlockId::Number(10)).unwrap() == Some(Vec::new())
if net
.peer(0)
.client()
.justifications(&BlockId::Number(10))
.unwrap() == Some(Justifications::from((*b"FRNK", Vec::new())))
&& net
.peer(1)
.client()
.justifications(&BlockId::Number(10))
.unwrap() == Some(Justifications::from((*b"FRNK", Vec::new())))
{
Poll::Ready(())
} else {
@@ -696,8 +717,9 @@ fn can_sync_to_peers_with_wrong_common_block() {
net.block_until_connected();
// both peers re-org to the same fork without notifying each other
net.peer(0).client().finalize_block(BlockId::Hash(fork_hash), Some(Vec::new()), true).unwrap();
net.peer(1).client().finalize_block(BlockId::Hash(fork_hash), Some(Vec::new()), true).unwrap();
let just = Some((*b"FRNK", Vec::new()));
net.peer(0).client().finalize_block(BlockId::Hash(fork_hash), just.clone(), true).unwrap();
net.peer(1).client().finalize_block(BlockId::Hash(fork_hash), just, true).unwrap();
let final_hash = net.peer(0).push_blocks(1, false);
net.block_until_sync();
@@ -948,8 +970,8 @@ fn multiple_requests_are_accepted_as_long_as_they_are_not_fulfilled() {
net.block_until_sync();
// there's currently no justification for block #10
assert_eq!(net.peer(0).client().justification(&BlockId::Number(10)).unwrap(), None);
assert_eq!(net.peer(1).client().justification(&BlockId::Number(10)).unwrap(), None);
assert_eq!(net.peer(0).client().justifications(&BlockId::Number(10)).unwrap(), None);
assert_eq!(net.peer(1).client().justifications(&BlockId::Number(10)).unwrap(), None);
let h1 = net.peer(1).client().header(&BlockId::Number(10)).unwrap().unwrap();
@@ -967,12 +989,21 @@ fn multiple_requests_are_accepted_as_long_as_they_are_not_fulfilled() {
}
// Finalize the block and make the justification available.
net.peer(0).client().finalize_block(BlockId::Number(10), Some(Vec::new()), true).unwrap();
net.peer(0).client().finalize_block(
BlockId::Number(10),
Some((*b"FRNK", Vec::new())),
true,
).unwrap();
block_on(futures::future::poll_fn::<(), _>(|cx| {
net.poll(cx);
if net.peer(1).client().justification(&BlockId::Number(10)).unwrap() != Some(Vec::new()) {
if net
.peer(1)
.client()
.justifications(&BlockId::Number(10))
.unwrap() != Some(Justifications::from((*b"FRNK", Vec::new())))
{
return Poll::Pending;
}