referrerpolicy=no-referrer-when-downgrade

bp_header_chain/justification/verification/
strict.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Parity Bridges Common.
3
4// Parity Bridges Common is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Parity Bridges Common is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Parity Bridges Common.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Logic for checking if GRANDPA Finality Proofs are valid and optimal.
18
19use crate::justification::{
20	verification::{Error, JustificationVerifier, PrecommitError},
21	GrandpaJustification,
22};
23
24use crate::justification::verification::{
25	IterationFlow, JustificationVerificationContext, SignedPrecommit,
26};
27use sp_consensus_grandpa::AuthorityId;
28use sp_runtime::traits::Header as HeaderT;
29use sp_std::{collections::btree_set::BTreeSet, vec::Vec};
30
31/// Verification callbacks that reject all unknown, duplicate or redundant votes.
32struct StrictJustificationVerifier {
33	votes: BTreeSet<AuthorityId>,
34}
35
36impl<Header: HeaderT> JustificationVerifier<Header> for StrictJustificationVerifier {
37	fn process_duplicate_votes_ancestries(
38		&mut self,
39		_duplicate_votes_ancestries: Vec<usize>,
40	) -> Result<(), Error> {
41		Err(Error::DuplicateVotesAncestries)
42	}
43
44	fn process_redundant_vote(
45		&mut self,
46		_precommit_idx: usize,
47	) -> Result<IterationFlow, PrecommitError> {
48		Err(PrecommitError::RedundantAuthorityVote)
49	}
50
51	fn process_known_authority_vote(
52		&mut self,
53		_precommit_idx: usize,
54		signed: &SignedPrecommit<Header>,
55	) -> Result<IterationFlow, PrecommitError> {
56		if self.votes.contains(&signed.id) {
57			// There's a lot of code in `validate_commit` and `import_precommit` functions
58			// inside `finality-grandpa` crate (mostly related to reporting equivocations).
59			// But the only thing that we care about is that only first vote from the
60			// authority is accepted
61			return Err(PrecommitError::DuplicateAuthorityVote)
62		}
63
64		Ok(IterationFlow::Run)
65	}
66
67	fn process_unknown_authority_vote(
68		&mut self,
69		_precommit_idx: usize,
70	) -> Result<(), PrecommitError> {
71		Err(PrecommitError::UnknownAuthorityVote)
72	}
73
74	fn process_unrelated_ancestry_vote(
75		&mut self,
76		_precommit_idx: usize,
77	) -> Result<IterationFlow, PrecommitError> {
78		Err(PrecommitError::UnrelatedAncestryVote)
79	}
80
81	fn process_invalid_signature_vote(
82		&mut self,
83		_precommit_idx: usize,
84	) -> Result<(), PrecommitError> {
85		Err(PrecommitError::InvalidAuthoritySignature)
86	}
87
88	fn process_valid_vote(&mut self, signed: &SignedPrecommit<Header>) {
89		self.votes.insert(signed.id.clone());
90	}
91
92	fn process_redundant_votes_ancestries(
93		&mut self,
94		_redundant_votes_ancestries: BTreeSet<Header::Hash>,
95	) -> Result<(), Error> {
96		Err(Error::RedundantVotesAncestries)
97	}
98}
99
100/// Verify that justification, that is generated by given authority set, finalizes given header.
101pub fn verify_justification<Header: HeaderT>(
102	finalized_target: (Header::Hash, Header::Number),
103	context: &JustificationVerificationContext,
104	justification: &GrandpaJustification<Header>,
105) -> Result<(), Error> {
106	let mut verifier = StrictJustificationVerifier { votes: BTreeSet::new() };
107	verifier.verify_justification(finalized_target, context, justification)
108}