From 149b198eab3bfa37fea718a01fea6a0099f0bea9 Mon Sep 17 00:00:00 2001 From: Qinxuan Chen Date: Fri, 3 Mar 2023 15:43:37 +0800 Subject: [PATCH] feat: add a new post log type into header digest and provide a compatible mapping-sync worker (#1011) --- Cargo.lock | 1 + client/mapping-sync/Cargo.toml | 1 + client/mapping-sync/src/lib.rs | 92 ++++++++++++++++++++++++------- client/mapping-sync/src/worker.rs | 12 +++- primitives/consensus/src/lib.rs | 31 ++++------- template/node/src/eth.rs | 1 + 6 files changed, 96 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b18ccfcde8..134ebd6ac0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1928,6 +1928,7 @@ name = "fc-mapping-sync" version = "2.0.0-dev" dependencies = [ "fc-db", + "fc-storage", "fp-consensus", "fp-rpc", "futures", diff --git a/client/mapping-sync/Cargo.toml b/client/mapping-sync/Cargo.toml index 80957cd616..5ca2705103 100644 --- a/client/mapping-sync/Cargo.toml +++ b/client/mapping-sync/Cargo.toml @@ -21,5 +21,6 @@ sp-blockchain = { workspace = true } sp-runtime = { workspace = true } # Frontier fc-db = { workspace = true } +fc-storage = { workspace = true } fp-consensus = { workspace = true, features = ["default"] } fp-rpc = { workspace = true, features = ["default"] } diff --git a/client/mapping-sync/src/lib.rs b/client/mapping-sync/src/lib.rs index f84397b327..70d5794968 100644 --- a/client/mapping-sync/src/lib.rs +++ b/client/mapping-sync/src/lib.rs @@ -22,8 +22,10 @@ mod worker; pub use worker::{MappingSyncWorker, SyncStrategy}; +use std::sync::Arc; + // Substrate -use sc_client_api::backend::Backend; +use sc_client_api::backend::{Backend, StorageProvider}; use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_blockchain::{Backend as _, HeaderBackend}; use sp_runtime::{ @@ -31,31 +33,78 @@ use sp_runtime::{ traits::{Block as BlockT, Header as HeaderT, Zero}, }; // Frontier -use fp_consensus::FindLogError; +use fc_storage::OverrideHandle; +use fp_consensus::{FindLogError, Hashes, Log, PostLog, PreLog}; use fp_rpc::EthereumRuntimeRPCApi; -pub fn sync_block( +pub fn sync_block( + client: &C, + overrides: Arc>, backend: &fc_db::Backend, header: &Block::Header, -) -> Result<(), String> { +) -> Result<(), String> +where + C: StorageProvider + HeaderBackend, + BE: Backend, +{ + let substrate_block_hash = header.hash(); match fp_consensus::find_log(header.digest()) { Ok(log) => { - let post_hashes = log.into_hashes(); - - let mapping_commitment = fc_db::MappingCommitment { - block_hash: header.hash(), - ethereum_block_hash: post_hashes.block_hash, - ethereum_transaction_hashes: post_hashes.transaction_hashes, + let gen_from_hashes = |hashes: Hashes| -> fc_db::MappingCommitment { + fc_db::MappingCommitment { + block_hash: substrate_block_hash, + ethereum_block_hash: hashes.block_hash, + ethereum_transaction_hashes: hashes.transaction_hashes, + } + }; + let gen_from_block = |block| -> fc_db::MappingCommitment { + let hashes = Hashes::from_block(block); + gen_from_hashes(hashes) }; - backend.mapping().write_hashes(mapping_commitment)?; - - Ok(()) - } - Err(FindLogError::NotFound) => { - backend.mapping().write_none(header.hash())?; - Ok(()) + match log { + Log::Pre(PreLog::Block(block)) => { + let mapping_commitment = gen_from_block(block); + backend.mapping().write_hashes(mapping_commitment) + } + Log::Post(post_log) => match post_log { + PostLog::Hashes(hashes) => { + let mapping_commitment = gen_from_hashes(hashes); + backend.mapping().write_hashes(mapping_commitment) + } + PostLog::Block(block) => { + let mapping_commitment = gen_from_block(block); + backend.mapping().write_hashes(mapping_commitment) + } + PostLog::BlockHash(expect_eth_block_hash) => { + let schema = + fc_storage::onchain_storage_schema(client, substrate_block_hash); + let ethereum_block = overrides + .schemas + .get(&schema) + .unwrap_or(&overrides.fallback) + .current_block(substrate_block_hash); + match ethereum_block { + Some(block) => { + let got_eth_block_hash = block.header.hash(); + if got_eth_block_hash != expect_eth_block_hash { + Err(format!( + "Ethereum block hash mismatch: \ + frontier consensus digest ({expect_eth_block_hash:?}), \ + db state ({got_eth_block_hash:?})" + )) + } else { + let mapping_commitment = gen_from_block(block); + backend.mapping().write_hashes(mapping_commitment) + } + } + None => backend.mapping().write_none(substrate_block_hash), + } + } + }, + } } + Err(FindLogError::NotFound) => backend.mapping().write_none(substrate_block_hash), Err(FindLogError::MultipleLogs) => Err("Multiple logs found".to_string()), } } @@ -109,6 +158,7 @@ where pub fn sync_one_block( client: &C, substrate_backend: &BE, + overrides: Arc>, frontier_backend: &fc_db::Backend, sync_from: ::Number, strategy: SyncStrategy, @@ -116,7 +166,7 @@ pub fn sync_one_block( where C: ProvideRuntimeApi, C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend, + C: HeaderBackend + StorageProvider, BE: Backend, { let mut current_syncing_tips = frontier_backend.meta().current_syncing_tips()?; @@ -167,7 +217,7 @@ where { return Ok(false); } - sync_block(frontier_backend, &operating_header)?; + sync_block(client, overrides, frontier_backend, &operating_header)?; current_syncing_tips.push(*operating_header.parent_hash()); frontier_backend @@ -180,6 +230,7 @@ where pub fn sync_blocks( client: &C, substrate_backend: &BE, + overrides: Arc>, frontier_backend: &fc_db::Backend, limit: usize, sync_from: ::Number, @@ -188,7 +239,7 @@ pub fn sync_blocks( where C: ProvideRuntimeApi, C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend, + C: HeaderBackend + StorageProvider, BE: Backend, { let mut synced_any = false; @@ -198,6 +249,7 @@ where || sync_one_block( client, substrate_backend, + overrides.clone(), frontier_backend, sync_from, strategy, diff --git a/client/mapping-sync/src/worker.rs b/client/mapping-sync/src/worker.rs index 6fbe25d705..06702cbe1a 100644 --- a/client/mapping-sync/src/worker.rs +++ b/client/mapping-sync/src/worker.rs @@ -25,11 +25,15 @@ use futures::{ use futures_timer::Delay; use log::debug; // Substrate -use sc_client_api::{backend::Backend, client::ImportNotifications}; +use sc_client_api::{ + backend::{Backend, StorageProvider}, + client::ImportNotifications, +}; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; use sp_runtime::traits::{Block as BlockT, Header as HeaderT}; // Frontier +use fc_storage::OverrideHandle; use fp_rpc::EthereumRuntimeRPCApi; #[derive(Copy, Clone, Eq, PartialEq)] @@ -45,6 +49,7 @@ pub struct MappingSyncWorker { client: Arc, substrate_backend: Arc, + overrides: Arc>, frontier_backend: Arc>, have_next: bool, @@ -61,6 +66,7 @@ impl MappingSyncWorker { timeout: Duration, client: Arc, substrate_backend: Arc, + overrides: Arc>, frontier_backend: Arc>, retry_times: usize, sync_from: ::Number, @@ -73,6 +79,7 @@ impl MappingSyncWorker { client, substrate_backend, + overrides, frontier_backend, have_next: true, @@ -87,7 +94,7 @@ impl Stream for MappingSyncWorker where C: ProvideRuntimeApi, C::Api: EthereumRuntimeRPCApi, - C: HeaderBackend, + C: HeaderBackend + StorageProvider, BE: Backend, { type Item = (); @@ -125,6 +132,7 @@ where match crate::sync_blocks( self.client.as_ref(), self.substrate_backend.as_ref(), + self.overrides.clone(), self.frontier_backend.as_ref(), self.retry_times, self.sync_from, diff --git a/primitives/consensus/src/lib.rs b/primitives/consensus/src/lib.rs index f66b782bad..370d3a40c6 100644 --- a/primitives/consensus/src/lib.rs +++ b/primitives/consensus/src/lib.rs @@ -34,16 +34,6 @@ pub enum Log { Post(PostLog), } -impl Log { - pub fn into_hashes(self) -> Hashes { - match self { - Log::Post(PostLog::Hashes(post_hashes)) => post_hashes, - Log::Post(PostLog::Block(block)) => Hashes::from_block(block), - Log::Pre(PreLog::Block(block)) => Hashes::from_block(block), - } - } -} - #[derive(Decode, Encode, Clone, PartialEq, Eq)] pub enum PreLog { #[codec(index = 3)] @@ -52,10 +42,15 @@ pub enum PreLog { #[derive(Decode, Encode, Clone, PartialEq, Eq)] pub enum PostLog { + /// Ethereum block hash and txn hashes. #[codec(index = 1)] Hashes(Hashes), + /// Ethereum block. #[codec(index = 2)] Block(ethereum::BlockV2), + /// Ethereum block hash. + #[codec(index = 3)] + BlockHash(H256), } #[derive(Decode, Encode, Clone, PartialEq, Eq)] @@ -68,17 +63,13 @@ pub struct Hashes { impl Hashes { pub fn from_block(block: ethereum::BlockV2) -> Self { - let mut transaction_hashes = Vec::new(); - - for t in &block.transactions { - transaction_hashes.push(t.hash()); - } - - let block_hash = block.header.hash(); - Hashes { - transaction_hashes, - block_hash, + block_hash: block.header.hash(), + transaction_hashes: block + .transactions + .into_iter() + .map(|txn| txn.hash()) + .collect(), } } } diff --git a/template/node/src/eth.rs b/template/node/src/eth.rs index 4bae5d9099..cf0b6c56b6 100644 --- a/template/node/src/eth.rs +++ b/template/node/src/eth.rs @@ -128,6 +128,7 @@ pub fn spawn_frontier_tasks( Duration::new(6, 0), client.clone(), backend, + overrides.clone(), frontier_backend, 3, 0,