Grandpa validator set handoff justification (#1190)

* core: make block justification optional

* runtime: update wasm binaries

* core: optionally pass justification on finalize_block

* finality-grandpa: add channel to trigger authority set changes

this will allow the `BlockImport` to trigger an authority set change when
importing a change block that provides a justification (when syncing)

* finality-grandpa: move finalize_block to free function

* finality-grandpa: add GrandpaOracle for auth set liveness checking

this will be used by `BlockImport` to check whether the authority set for a
given block is still live, if the authority set isn't live then importing a
change block requires a justification.

* finality-grandpa: store justification on finalized transition blocks

* finality-grandpa: check justification on authority set change blocks

* finality-grandpa: poll grandpa liveness oracle every 10 seconds

* finality-grandpa: spawn grandpa oracle in service setup

* core: support multiple subscriptions per consensus gossip topic

* finality-grandpa: create and verify justifications

* finality-grandpa: update to local branch of grandpa

* finality-grandpa: update to finality-grandpa v0.5.0

* finality-grandpa: move grandpa oracle code

* finality-grandpa: fix canonality check

* finality-grandpa: clean up error handling

* finality-grandpa: fix canonical_at_height

* finality-grandpa: fix tests

* runtime: update wasm binaries

* core: add tests for finalizing block with justification

* finality-grandpa: improve validation of justifications

* core: remove unused IncompleteJustification block import error

* core: test multiple subscribers for same consensus gossip topic

* Revert "finality-grandpa: improve validation of justifications"

This reverts commit 51eb2c58c2219801e876af6d6c9371bdd9ff2477.

* finality-grandpa: fix commit validation

* finality-grandpa: fix commit ancestry validation

* finality-grandpa: use grandpa v0.5.1

* finality-grandpa: add docs

* finality-grandpa: fix failing test

* finality-grandpa: only allow a pending authority set change per fork

* finality-grandpa: fix validator set transition test
This commit is contained in:
André Silva
2018-12-08 05:34:59 +00:00
committed by Gav Wood
parent da822276dd
commit e779eeb2ec
29 changed files with 1115 additions and 389 deletions
+48 -3
View File
@@ -797,7 +797,9 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
Ok(())
}
fn finalize_block(&self, block: BlockId<Block>) -> Result<(), client::error::Error> {
fn finalize_block(&self, block: BlockId<Block>, justification: Option<Justification>)
-> Result<(), client::error::Error>
{
use runtime_primitives::traits::Header;
if let Some(header) = ::client::blockchain::HeaderBackend::header(&self.blockchain, block)? {
@@ -805,6 +807,14 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
// TODO: ensure best chain contains this block.
let hash = header.hash();
self.note_finalized(&mut transaction, &header, hash.clone())?;
if let Some(justification) = justification {
let number = header.number().clone();
transaction.put(
columns::JUSTIFICATION,
&::utils::number_and_hash_to_lookup_key(number, hash.clone()),
&justification.encode(),
);
}
self.storage.db.write(transaction).map_err(db_err)?;
self.blockchain.update_meta(hash, header.number().clone(), false, true);
Ok(())
@@ -1196,8 +1206,8 @@ mod tests {
assert!(backend.storage.db.get(::columns::STATE, key.as_bytes()).unwrap().is_none());
}
backend.finalize_block(BlockId::Number(1)).unwrap();
backend.finalize_block(BlockId::Number(2)).unwrap();
backend.finalize_block(BlockId::Number(1), None).unwrap();
backend.finalize_block(BlockId::Number(2), None).unwrap();
assert!(backend.storage.db.get(::columns::STATE, key.as_bytes()).unwrap().is_none());
}
@@ -1499,4 +1509,39 @@ mod tests {
backend.insert_aux(&[], &[&b"test"[..]]).unwrap();
assert!(backend.get_aux(b"test").unwrap().is_none());
}
#[test]
fn test_finalize_block_with_justification() {
use client::blockchain::{Backend as BlockChainBackend};
let backend = Backend::<Block>::new_test(0, 0);
{
let mut op = backend.begin_operation(BlockId::Hash(Default::default())).unwrap();
let header = Header {
number: 0,
parent_hash: Default::default(),
state_root: Default::default(),
digest: Default::default(),
extrinsics_root: Default::default(),
};
op.set_block_data(
header,
Some(vec![]),
None,
NewBlockState::Best,
).unwrap();
backend.commit_operation(op).unwrap();
}
let justification = Some(vec![1, 2, 3]);
backend.finalize_block(BlockId::Number(0), justification.clone()).unwrap();
assert_eq!(
backend.blockchain().justification(BlockId::Number(0)).unwrap(),
justification,
);
}
}