-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Conversation
|
||
#[test] | ||
fn rejects_step_backwards() { | ||
let tap = AccountProvider::transient_provider(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indent
To give a quick run-down of what's still left to do:
This implementation will be in a separate branch. |
I'm mildly concerned about how |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, lg in general. I like the Unsure
stuff to keep state out of Engine
. For Mutli
maybe handling the recursive case is possible as mentioned.
use error::Error; | ||
use header::Header; | ||
|
||
/// Verifier for all blocks within an epoch without accessing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfinished
pub type ChunkSink<'a> = FnMut(&[u8]) -> io::Result<()> + 'a; | ||
|
||
// How many blocks to include in a snapshot, starting from the head of the chain. | ||
const SNAPSHOT_BLOCKS: u64 = 30000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be Engine
specific? Different ones have different security requirements.
@@ -380,6 +390,12 @@ impl Client { | |||
return Err(()); | |||
}; | |||
|
|||
let verify_external_result = self.verifier.verify_block_external(header, &block.bytes, engine); | |||
if let Err(e) = verify_external_result { | |||
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stage 4 is here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(changed that to stage 5)
self.correct_set_by_number(header.number()).1.epoch_proof(header, caller) | ||
} | ||
|
||
fn epoch_set(&self, header: &Header, proof: &[u8]) -> Result<(u64, super::SimpleList), ::error::Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe pass the previous block epoch nonce and return ValidatorSet
instead of SimpleList
? Then you can bump the nonce on recursive call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
main problem there is that it's hard to say what the previous block epoch nonce would be without recovering it; meaning you have to package two state proofs for each transition in warp/light rather than one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
right now, I think it's pretty fair to say that nested multi-sets don't make any sense -- we might just want to rewrite the validator set constructor to take a flag indicating whether we're at the top level (set false before recursing) and throw an error on nested multi set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, though this makes SimpleList
a special fundamental ValidatorSet
rather than just another trait implementation. But I guess that's fine since there are no other scenarios yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with generalizing a bit later, but all current validator sets can express themselves as a SimpleList
at any given block, and we need the property of fast verification of blocks out-of-order for the epoch verifier.
(tagging on behalf of @keorn) |
Makes changes to the
engines
module that will allow warp sync, ancient block download, and light client sync to work for even complex engines.Engines now detect and generate data for epoch changes. State proofs validating this data, along with the transitions themselves, are stored in the blockchain extras DB.
Snapshot block chunks are repurposed to a more general "secondary chunks" which engine-specific snapshot components will create and interpret as a means to corroborate the data within the snapshot state chunks. For proof-of-work engines, these chunks will be as specified in the wiki.
PoA engines like Aura and BasicAuthority will include all transitions in the snapshot, as described in #5427.
Ancient block download/light sync will make use of an
EpochVerifier
that caches an in-memory list of validators derived from the validated transitions obtained in the snapshot (or in the light client case, from the network). When epoch changes occur, we simply obtain a newEpochVerifier
for that epoch. Ethash epochs don't currently make use of this mechanism, and just pretend that the chain is under one "epoch" so we never need to swap, but could be altered to in the future to ensure our DAG caching is completely optimal.This approach isn't completely resilient (and indeed, won't really work for something like rinkeby's clique consensus; for that I'd wait on introducing engine-specific storage and have
clique
snapshots contain the entire headerchain.), but it will get the job done for now.The "genesis epoch" has number 0, so any epochs beyond that must start with
1
, otherwise warp and light sync will break.