-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Verify Grandpa proofs from within runtime #4167
Verify Grandpa proofs from within runtime #4167
Conversation
…tytech#3874) * Make tests work after the changes introduced in paritytech#3793 * Remove unneccessary import
…ytech#3915) * Make StorageProofChecker happy * Update some tests * Check given validator set against set found in storage * Use Finality Grandpa's Authority Id and Weight * Add better error handling * Use error type from decl_error! macro
* Create module for checking ancestry proofs * Use Vec of Headers instead of a HashMap * Move the ancestry verification into the lib.rs file * Change the proof format to exclude `child` and `ancestor` headers * Add a testing function for building header chains * Rename AncestorNotFound error to InvalidAncestryProof * Use ancestor hash instead of header when verifying ancestry * Clean up some stuff missed in the merge
This comment has been minimized.
This comment has been minimized.
As @svyatonik pointed out to me, not all the functions are needed by the bridge module (e.g |
/// This is meant to be stored in the db and passed around the network to other | ||
/// nodes, and are used by syncing nodes to prove authority set handoffs. | ||
#[derive(Encode, Decode)] | ||
pub struct GrandpaJustification<Block: BlockT> { |
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 feel like the contents of this module should be in the palette/grandpa
crate, since it's generally useful.
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.
IMO it should go into primitives/finality-grandpa
and then it gets used by both client and pallet code (and also by the bridge pallet).
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 going to wait until I rebase past the-big-reorg
before moving the code into primitives/finality-grandpa
.
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 think migrating to BTrees is sensible, we just did the same thing on the finality-grandpa
crate.
if as_public.verify(&encoded_raw, signature) { | ||
Ok(()) | ||
} else { | ||
// debug!(target: "afg", "Bad signature on message from {:?}", id); |
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.
We probably want to keep this for the client code that uses it once this is refactored to re-use the same code.
There are a couple of things that I want to do in later PRs:
I think it's fine to get this PR in without these two things. Once this is merged I can then go ahead and rebase the whole bridge branch past |
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.
Just did a very cursory review as you need to drop some disallowed dependencies which show up in a bunch of places.
@@ -8,9 +8,15 @@ edition = "2018" | |||
|
|||
[dependencies] | |||
codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false } | |||
client = { package = "substrate-client", path = "../../core/client" } | |||
fg = { package = "substrate-finality-grandpa", path = "../../core/finality-grandpa/" } |
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.
You can't import this.
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 gonna wait on #3868 before getting rid of it
I think it's going to be a little annoying to get rid of the |
I think some of the |
|
||
use codec::{Encode, Decode}; | ||
use core::cmp::{Ord, Ordering}; | ||
// TODO: Since I can't use types from `core/finality-grandpa`, wait until #3868 |
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.
Put this TODO in the Cargo.toml too, which is more important.
/// targets should be the same as the commit target, since honest voters don't | ||
/// vote past authority set change blocks. | ||
/// | ||
/// This is meant to be stored in the db and passed around the network to other |
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.
This part of the comment seems wrong (stored in the db and networked).
/// Create a GRANDPA justification from the given commit. This method | ||
/// assumes the commit is valid and well-formed. | ||
#[cfg(test)] | ||
pub(crate) fn from_commit<B, E, RA>( |
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.
nit: Just make it pub
, not pub(crate)
. The module is private.
let mut votes_ancestries_hashes = BTreeSet::new(); | ||
let mut votes_ancestries = Vec::new(); | ||
|
||
let 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.
I would just inline this.
|
||
/// Decode a GRANDPA justification and validate the commit and the votes' | ||
/// ancestry proofs finalize the given block. | ||
pub(crate) fn decode_and_verify_finalizes( |
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.
nit: pub
} | ||
|
||
#[cfg_attr(test, derive(Debug))] | ||
pub(crate) enum JustificationError { |
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.
You can get rid of this. Just use the normal error type. Any function that returns Result<(), JustificationError>
where the error is always BadJustification
(like from_commit
and verify
) can return an error type of ()
.
|
||
impl<Block: BlockT> AncestryChain<Block> { | ||
fn new(ancestry: &[Block::Header]) -> AncestryChain<Block> { | ||
let ancestry: BTreeMap<_, _> = ancestry |
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.
nit: this type hint shouldn't be necessary.
/// This is useful when validating commits, using the given set of headers to | ||
/// verify a valid ancestry route to the target commit block. | ||
struct AncestryChain<Block: BlockT> { | ||
ancestry: BTreeMap<BlockHashKey<Block>, Block::Header>, |
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.
Perhaps not necessary, but this could be a BTreeMap<BlockHashKey<Block>, &'a Block::Header>
(map to header refs to avoid cloning).
Error::InvalidAncestryProof | ||
); | ||
} | ||
|
||
// Currently stealing this from `core/finality-grandpa/src/test.rs` |
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.
Do you expect it to be replaced? Otherwise, don't say "Currently".
use trie::{MemoryDB, Trie, trie_types::TrieDB}; | ||
|
||
use crate::Error; | ||
|
||
pub(crate) type StorageProof = Vec<Vec<u8>>; |
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.
pub
I talked with Jim about some of the options for moving this forward. Since there's a lot of code that came from
We think that the best way forward is (2) as it'll allow us to have a cleaner implementation that doesn't duplicate Grandpa code. |
50c6a2f
to
4f7397d
Compare
296d8a4
to
2064106
Compare
Closing in favour of paritytech/parity-bridges-common#19. |
I'm looking to get some feedback on this. For the bridge module, we need to be able to verify the validity of Grandpa proofs. The problem is however, that there is no way to do this from within the runtime as the current Grandpa proof code requires
std
. What I've done here is taken some of the code from the Substratefinality-grandpa
crate and modified it to make it work in ano_std
environment. The two main changes were:HashMap
andHashSet
toBTreeMap
andBTreeSet
AuthorityPair
for signature verification, to usingAuthoritySignature
+RuntimeAppPublic
Ideally this code wouldn't be duplicated in two places, but right now I'm just trying to make this work in the context of the bridge module.
Before merging this PR I'd like to have the
submit_finalized_headers()
function actually using the new code to verify Grandpa proofs.