This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Lean BEEFY to Full BEEFY - don't skip (older) mandatory blocks and import justifications #11821
Merged
paritytech-processbot
merged 25 commits into
paritytech:master
from
acatangiu:beefy-import-justif
Jul 29, 2022
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
c4efa5f
client/beefy: don't accept vote for older rounds
acatangiu 934f14c
client/beefy: clean up and reorg the worker struct
acatangiu 2f1f221
client/beefy: first step towards Full BEEFY
acatangiu d732f82
client/beefy: sketch idea for block import and sync
acatangiu b70b9be
client/beefy: add BEEFY block import
acatangiu 1d0298c
client/beefy: process justifications from block import
acatangiu 6d381db
client/beefy: add TODOs for sync protocol
acatangiu 739898a
client/beefy: add more docs and comments
acatangiu abfd074
client/beefy-rpc: fix RPC error
acatangiu 46de909
client/beefy: verify justification validity on block import
acatangiu efe0157
client/beefy: more tests
acatangiu e129702
client/beefy: small fixes
acatangiu 0540091
client/beefy: remove invalid justifications at block import
acatangiu 2c16427
todo: beefy block import tests
acatangiu 8256fb0
RFC: ideas for multiple justifications per block
acatangiu d5b53ae
Revert "RFC: ideas for multiple justifications per block"
acatangiu bc6a187
client/beefy: append justif to backend on block import
acatangiu 73355d0
client/beefy: groundwork for block import test
acatangiu d5f9f1a
client/beefy: groundwork2 for block import test
acatangiu ff02b1a
client/beefy: groundwork3 for block import test
acatangiu 1c49f49
client/beefy: add block import test
acatangiu 9761f89
Merge branch 'master' of github.com:paritytech/substrate into beefy-i…
acatangiu ecf625b
client/beefy: add required trait bounds to block import builder
acatangiu 0d843e0
remove client from beefy block import, backend gets the job done
acatangiu 581b5ab
Merge branch 'master' of github.com:paritytech/substrate into beefy-i…
acatangiu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,205 @@ | ||
| // This file is part of Substrate. | ||
|
|
||
| // Copyright (C) 2021-2022 Parity Technologies (UK) Ltd. | ||
| // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 | ||
|
|
||
| // This program is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
|
|
||
| // This program is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License for more details. | ||
|
|
||
| // You should have received a copy of the GNU General Public License | ||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
|
||
| use beefy_primitives::{crypto::Signature, BeefyApi, VersionedFinalityProof, BEEFY_ENGINE_ID}; | ||
| use codec::Encode; | ||
| use log::error; | ||
| use std::{collections::HashMap, sync::Arc}; | ||
|
|
||
| use sp_api::{ProvideRuntimeApi, TransactionFor}; | ||
| use sp_blockchain::{well_known_cache_keys, HeaderBackend}; | ||
| use sp_consensus::Error as ConsensusError; | ||
| use sp_runtime::{ | ||
| generic::BlockId, | ||
| traits::{Block as BlockT, Header as HeaderT, NumberFor}, | ||
| EncodedJustification, | ||
| }; | ||
|
|
||
| use sc_client_api::backend::Backend; | ||
| use sc_consensus::{BlockCheckParams, BlockImport, BlockImportParams, ImportResult}; | ||
|
|
||
| use crate::{ | ||
| justification::decode_and_verify_commitment, notification::BeefySignedCommitmentSender, | ||
| }; | ||
|
|
||
| /// A block-import handler for BEEFY. | ||
| /// | ||
| /// This scans each imported block for BEEFY justifications and verifies them. | ||
| /// Wraps a `inner: BlockImport` and ultimately defers to it. | ||
| /// | ||
| /// When using BEEFY, the block import worker should be using this block import object. | ||
| pub struct BeefyBlockImport<Block: BlockT, Backend, RuntimeApi, I> { | ||
| backend: Arc<Backend>, | ||
| runtime: Arc<RuntimeApi>, | ||
| inner: I, | ||
| justification_sender: BeefySignedCommitmentSender<Block>, | ||
| } | ||
|
|
||
| impl<Block: BlockT, BE, Runtime, I: Clone> Clone for BeefyBlockImport<Block, BE, Runtime, I> { | ||
| fn clone(&self) -> Self { | ||
| BeefyBlockImport { | ||
| backend: self.backend.clone(), | ||
| runtime: self.runtime.clone(), | ||
| inner: self.inner.clone(), | ||
| justification_sender: self.justification_sender.clone(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<Block: BlockT, BE, Runtime, I> BeefyBlockImport<Block, BE, Runtime, I> { | ||
| /// Create a new BeefyBlockImport. | ||
| pub fn new( | ||
| backend: Arc<BE>, | ||
| runtime: Arc<Runtime>, | ||
| inner: I, | ||
| justification_sender: BeefySignedCommitmentSender<Block>, | ||
| ) -> BeefyBlockImport<Block, BE, Runtime, I> { | ||
| BeefyBlockImport { backend, runtime, inner, justification_sender } | ||
| } | ||
| } | ||
|
|
||
| impl<Block, BE, Runtime, I> BeefyBlockImport<Block, BE, Runtime, I> | ||
| where | ||
| Block: BlockT, | ||
| BE: Backend<Block>, | ||
| Runtime: ProvideRuntimeApi<Block>, | ||
| Runtime::Api: BeefyApi<Block> + Send + Sync, | ||
| { | ||
| fn decode_and_verify( | ||
| &self, | ||
| encoded: &EncodedJustification, | ||
| number: NumberFor<Block>, | ||
| hash: <Block as BlockT>::Hash, | ||
| ) -> Result<VersionedFinalityProof<NumberFor<Block>, Signature>, ConsensusError> { | ||
| let block_id = BlockId::hash(hash); | ||
| let validator_set = self | ||
| .runtime | ||
| .runtime_api() | ||
| .validator_set(&block_id) | ||
| .map_err(|e| ConsensusError::ClientImport(e.to_string()))? | ||
| .ok_or_else(|| ConsensusError::ClientImport("Unknown validator set".to_string()))?; | ||
|
|
||
| decode_and_verify_commitment::<Block>(&encoded[..], number, &validator_set) | ||
| } | ||
|
|
||
| /// Import BEEFY justification: Send it to worker for processing and also append it to backend. | ||
| /// | ||
| /// This function assumes: | ||
| /// - `justification` is verified and valid, | ||
| /// - the block referred by `justification` has been imported _and_ finalized. | ||
| fn import_beefy_justification_unchecked( | ||
| &self, | ||
| number: NumberFor<Block>, | ||
| justification: VersionedFinalityProof<NumberFor<Block>, Signature>, | ||
| ) { | ||
| // Append the justification to the block in the backend. | ||
| if let Err(e) = self.backend.append_justification( | ||
| BlockId::Number(number), | ||
| (BEEFY_ENGINE_ID, justification.encode()), | ||
| ) { | ||
| error!(target: "beefy", "🥩 Error {:?} on appending justification: {:?}", e, justification); | ||
| } | ||
| // Send the justification to the BEEFY voter for processing. | ||
| match justification { | ||
| // TODO #11838: Should not unpack, these channels should also use | ||
| // `VersionedFinalityProof`. | ||
| VersionedFinalityProof::V1(signed_commitment) => self | ||
| .justification_sender | ||
| .notify(|| Ok::<_, ()>(signed_commitment)) | ||
| .expect("forwards closure result; the closure always returns Ok; qed."), | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| #[async_trait::async_trait] | ||
| impl<Block, BE, Runtime, I> BlockImport<Block> for BeefyBlockImport<Block, BE, Runtime, I> | ||
| where | ||
| Block: BlockT, | ||
| BE: Backend<Block>, | ||
| I: BlockImport< | ||
| Block, | ||
| Error = ConsensusError, | ||
| Transaction = sp_api::TransactionFor<Runtime, Block>, | ||
| > + Send | ||
| + Sync, | ||
| Runtime: ProvideRuntimeApi<Block> + Send + Sync, | ||
| Runtime::Api: BeefyApi<Block>, | ||
| { | ||
| type Error = ConsensusError; | ||
| type Transaction = TransactionFor<Runtime, Block>; | ||
|
|
||
| async fn import_block( | ||
| &mut self, | ||
| mut block: BlockImportParams<Block, Self::Transaction>, | ||
| new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>, | ||
| ) -> Result<ImportResult, Self::Error> { | ||
| let hash = block.post_hash(); | ||
| let number = *block.header.number(); | ||
|
|
||
| let beefy_proof = block | ||
| .justifications | ||
| .as_mut() | ||
| .and_then(|just| { | ||
| let decoded = just | ||
| .get(BEEFY_ENGINE_ID) | ||
| .map(|encoded| self.decode_and_verify(encoded, number, hash)); | ||
| // Remove BEEFY justification from the list before giving to `inner`; | ||
| // we will append it to backend ourselves at the end if all goes well. | ||
| just.remove(BEEFY_ENGINE_ID); | ||
| decoded | ||
| }) | ||
| .transpose() | ||
| .unwrap_or(None); | ||
|
|
||
| // Run inner block import. | ||
| let inner_import_result = self.inner.import_block(block, new_cache).await?; | ||
|
|
||
| match (beefy_proof, &inner_import_result) { | ||
| (Some(proof), ImportResult::Imported(_)) => { | ||
| let status = self.backend.blockchain().info(); | ||
| if number <= status.finalized_number && | ||
| Some(hash) == | ||
| self.backend | ||
| .blockchain() | ||
| .hash(number) | ||
| .map_err(|e| ConsensusError::ClientImport(e.to_string()))? | ||
| { | ||
| // The proof is valid and the block is imported and final, we can import. | ||
| self.import_beefy_justification_unchecked(number, proof); | ||
| } else { | ||
| error!( | ||
| target: "beefy", | ||
| "🥩 Cannot import justification: {:?} for, not yet final, block number {:?}", | ||
| proof, | ||
| number, | ||
| ); | ||
| } | ||
| }, | ||
| _ => (), | ||
| } | ||
|
|
||
| Ok(inner_import_result) | ||
| } | ||
|
|
||
| async fn check_block( | ||
| &mut self, | ||
| block: BlockCheckParams<Block>, | ||
| ) -> Result<ImportResult, Self::Error> { | ||
| self.inner.check_block(block).await | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.