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
@@ -39,7 +39,7 @@ use sp_consensus::{
import_queue::BoxJustificationImport,
};
use std::{collections::{HashMap, HashSet}, pin::Pin};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT};
use sp_runtime::{Justifications, traits::{Block as BlockT, Header as HeaderT}};
use sp_runtime::generic::{BlockId, DigestItem};
use sp_core::H256;
use sp_keystore::{SyncCryptoStorePtr, SyncCryptoStore};
@@ -369,7 +369,7 @@ fn finalize_3_voters_no_observers() {
// normally there's no justification for finalized blocks
assert!(
net.lock().peer(0).client().justification(&BlockId::Number(20)).unwrap().is_none(),
net.lock().peer(0).client().justifications(&BlockId::Number(20)).unwrap().is_none(),
"Extra justification for block#1",
);
}
@@ -613,7 +613,7 @@ fn justification_is_generated_periodically() {
// when block#32 (justification_period) is finalized, justification
// is required => generated
for i in 0..3 {
assert!(net.lock().peer(i).client().justification(&BlockId::Number(32)).unwrap().is_some());
assert!(net.lock().peer(i).client().justifications(&BlockId::Number(32)).unwrap().is_some());
}
}
@@ -658,12 +658,12 @@ fn sync_justifications_on_change_blocks() {
// the first 3 peers are grandpa voters and therefore have already finalized
// block 21 and stored a justification
for i in 0..3 {
assert!(net.lock().peer(i).client().justification(&BlockId::Number(21)).unwrap().is_some());
assert!(net.lock().peer(i).client().justifications(&BlockId::Number(21)).unwrap().is_some());
}
// the last peer should get the justification by syncing from other peers
futures::executor::block_on(futures::future::poll_fn(move |cx| {
if net.lock().peer(3).client().justification(&BlockId::Number(21)).unwrap().is_none() {
if net.lock().peer(3).client().justifications(&BlockId::Number(21)).unwrap().is_none() {
net.lock().poll(cx);
Poll::Pending
} else {
@@ -868,7 +868,7 @@ fn test_bad_justification() {
let block = || {
let block = block.clone();
let mut import = BlockImportParams::new(BlockOrigin::File, block.header);
import.justification = Some(Vec::new());
import.justifications = Some(Justifications::from((GRANDPA_ENGINE_ID, Vec::new())));
import.body = Some(block.extrinsics);
import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
@@ -1583,7 +1583,7 @@ fn imports_justification_for_regular_blocks_on_import() {
// we import the block with justification attached
let mut import = BlockImportParams::new(BlockOrigin::File, block.header);
import.justification = Some(justification.encode());
import.justifications = Some((GRANDPA_ENGINE_ID, justification.encode()).into());
import.body = Some(block.extrinsics);
import.fork_choice = Some(ForkChoiceStrategy::LongestChain);
@@ -1600,7 +1600,7 @@ fn imports_justification_for_regular_blocks_on_import() {
// the justification should be imported and available from the client
assert!(
client.justification(&BlockId::Hash(block_hash)).unwrap().is_some(),
client.justifications(&BlockId::Hash(block_hash)).unwrap().is_some(),
);
}