Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0fe90f7
core: make block justification optional
andresilva Nov 23, 2018
c9fdc56
runtime: update wasm binaries
andresilva Nov 23, 2018
cafa497
core: optionally pass justification on finalize_block
andresilva Nov 24, 2018
1fe5554
finality-grandpa: add channel to trigger authority set changes
andresilva Nov 26, 2018
8489541
finality-grandpa: move finalize_block to free function
andresilva Nov 27, 2018
208f097
finality-grandpa: add GrandpaOracle for auth set liveness checking
andresilva Nov 27, 2018
0c2912e
finality-grandpa: store justification on finalized transition blocks
andresilva Nov 28, 2018
b085e2e
finality-grandpa: check justification on authority set change blocks
andresilva Nov 28, 2018
fc284f7
finality-grandpa: poll grandpa liveness oracle every 10 seconds
andresilva Nov 29, 2018
4a90ba7
finality-grandpa: spawn grandpa oracle in service setup
andresilva Nov 30, 2018
0afa153
core: support multiple subscriptions per consensus gossip topic
andresilva Nov 30, 2018
4739e32
finality-grandpa: create and verify justifications
andresilva Nov 30, 2018
e4d5616
finality-grandpa: update to local branch of grandpa
andresilva Nov 30, 2018
f5ce910
finality-grandpa: update to finality-grandpa v0.5.0
andresilva Dec 2, 2018
711208b
finality-grandpa: move grandpa oracle code
andresilva Dec 2, 2018
cc46a45
finality-grandpa: fix canonality check
andresilva Dec 2, 2018
bac890e
finality-grandpa: clean up error handling
andresilva Dec 2, 2018
debd3b6
finality-grandpa: fix canonical_at_height
andresilva Dec 2, 2018
128eee0
finality-grandpa: fix tests
andresilva Dec 2, 2018
252817c
runtime: update wasm binaries
andresilva Dec 2, 2018
33392f5
core: add tests for finalizing block with justification
andresilva Dec 4, 2018
51eb2c5
finality-grandpa: improve validation of justifications
andresilva Dec 4, 2018
4a95dc3
core: remove unused IncompleteJustification block import error
andresilva Dec 4, 2018
101cba6
core: test multiple subscribers for same consensus gossip topic
andresilva Dec 4, 2018
a9e659b
Revert "finality-grandpa: improve validation of justifications"
andresilva Dec 5, 2018
d708849
finality-grandpa: fix commit validation
andresilva Dec 5, 2018
3ee13e0
Merge branch 'master' into andre/grandpa-handoff-justification
andresilva Dec 5, 2018
3f5732f
finality-grandpa: fix commit ancestry validation
andresilva Dec 5, 2018
1318a79
finality-grandpa: use grandpa v0.5.1
andresilva Dec 5, 2018
e5c593c
finality-grandpa: add docs
andresilva Dec 5, 2018
3a501ba
finality-grandpa: fix failing test
andresilva Dec 5, 2018
1e759d3
finality-grandpa: only allow a pending authority set change per fork
andresilva Dec 6, 2018
8c1981f
finality-grandpa: fix validator set transition test
andresilva Dec 7, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
finality-grandpa: check justification on authority set change blocks
  • Loading branch information
andresilva committed Nov 28, 2018
commit b085e2e2e3497fac91f42ab42ad23b9e666f011a
15 changes: 15 additions & 0 deletions core/finality-grandpa/src/authorities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,21 @@ where

Ok(status)
}

pub fn enacts_change<F, E>(&self, just_finalized: N, mut canonical: F)
-> Result<bool, E>
where F: FnMut(N) -> Result<H, E>
{
for change in self.pending_changes.iter() {
if change.effective_number() > just_finalized { break };

// check if the block that signalled the change is canonical in
// our chain.
let canonical_at_height = canonical(change.canon_height.clone())?;
if canonical_at_height == change.canon_hash { return Ok(true); }
}
Ok(false)
}
}

/// A pending change to the authority set.
Expand Down
66 changes: 62 additions & 4 deletions core/finality-grandpa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ extern crate parity_codec_derive;
use futures::prelude::*;
use futures::sync::mpsc;
use client::{
Client, error::Error as ClientError, backend::Backend, CallExecutor, BlockchainEvents
BlockchainEvents, CallExecutor, Client, backend::Backend,
error::Error as ClientError, error::ErrorKind as ClientErrorKind,
};
use client::blockchain::HeaderBackend;
use client::runtime_api::TaggedTransactionQueue;
Expand Down Expand Up @@ -706,6 +707,24 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> BlockImport<Block>
{
use authorities::PendingChange;

let enacts_change = self.authority_set.inner().read().enacts_change(*block.header.number(), |canon_number| {
self.inner.block_hash_from_id(&BlockId::number(canon_number))
.map(|h| h.expect("given number always less than block to finalize number; \
block to finalize number less or equal than best block number; \
thus there is a block with that number in the canon chain already; qed"))
})?;
let is_live = self.authority_set_oracle.is_live().unwrap_or(false);
let justification_provided = block.justification.is_some();

// a pending change is enacted by the given block, if the current
// grandpa authority set isn't live anymore the provided `ImportBlock`
// should include a justification for finalizing the block.
if enacts_change && !is_live && !justification_provided {
return Err(ClientErrorKind::BadJustification(
"missing justification for block that enacts authority set changes".to_string()
).into());
}

let maybe_change = self.api.runtime_api().grandpa_pending_change(
&BlockId::hash(*block.header.parent_hash()),
&block.header.digest().clone(),
Expand All @@ -731,15 +750,54 @@ impl<B, E, Block: BlockT<Hash=H256>, RA, PRA> BlockImport<Block>
(old_set, authorities)
});

let result = self.inner.import_block(block, new_authorities);
if let Err(ref e) = result {
let hash = block.header.hash();
let number = *block.header.number();
let justification = block.justification.clone();

let import_result = self.inner.import_block(block, new_authorities).map_err(|e| {
if let Some((old_set, mut authorities)) = just_in_case {
debug!(target: "afg", "Restoring old set after block import error: {:?}", e);
*authorities = old_set;
}
e
})?;

if let Some(justification) = justification {
// FIXME: validate justification
let justification = GrandpaJustification::decode(&mut &*justification).unwrap();

let result = finalize_block(
&*self.inner,
&self.authority_set,
hash,
number,
justification.into(),
);

match result {
Ok(_) if enacts_change => {
unreachable!("returns Ok when no authority set change should be enacted; \
verified previously that finalizing the current block enacts a change; \
qed;");
},
Err(ExitOrError::AuthoritiesChanged(new)) => {
if let Err(_) = self.authority_set_change.unbounded_send(new) {
return Err(ClientErrorKind::Backend(
"imported and finalized change block but grandpa voter is no longer running".to_string()
).into());
}
},
Err(ExitOrError::Error(_)) if enacts_change && !is_live => {
// FIXME: improve this
return Err(ClientErrorKind::Backend(
"imported change block but failed to finalize it, node may be in an inconsistent state".to_string()
).into());
},
_ => {},
}
}

result
Ok(import_result)
}
}

Expand Down