From 72457642702df981714bff727ecd6451aed60e9b Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Tue, 7 May 2024 19:48:24 -0400 Subject: [PATCH 01/34] Populate prev root from last block before regenesis --- crates/chain-config/src/config/state.rs | 3 +++ crates/fuel-core/src/service/genesis.rs | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index ffef804f907..a8444d36bed 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -89,6 +89,8 @@ pub struct LastBlockConfig { pub consensus_parameters_version: ConsensusParametersVersion, /// The version of state transition function used to produce last block. pub state_transition_version: StateTransitionBytecodeVersion, + /// The block id of the last block + pub block_hash: Bytes32, } impl From for LastBlockConfig { @@ -108,6 +110,7 @@ impl From<&BlockHeader> for LastBlockConfig { state_transition_version: header .application() .state_transition_bytecode_version, + block_hash: header.consensus().prev_root, } } } diff --git a/crates/fuel-core/src/service/genesis.rs b/crates/fuel-core/src/service/genesis.rs index a1b879adf5d..ebaf8d55021 100644 --- a/crates/fuel-core/src/service/genesis.rs +++ b/crates/fuel-core/src/service/genesis.rs @@ -178,6 +178,7 @@ pub fn create_genesis_block(config: &Config) -> Block { let da_height; let consensus_parameters_version; let state_transition_bytecode_version; + let prev_root; // If the rollup continues the old rollup, the height of the new block should // be higher than that of the old chain by one to make it continuous. @@ -196,8 +197,8 @@ pub fn create_genesis_block(config: &Config) -> Block { .state_transition_version .checked_add(1) .expect("State transition bytecode version overflow"); - da_height = latest_block.da_block_height; + prev_root = latest_block.block_hash; } else { height = 0u32.into(); #[cfg(feature = "relayer")] @@ -214,6 +215,7 @@ pub fn create_genesis_block(config: &Config) -> Block { } consensus_parameters_version = ConsensusParametersVersion::MIN; state_transition_bytecode_version = StateTransitionBytecodeVersion::MIN; + prev_root = Bytes32::zeroed(); } let transactions_ids = vec![]; @@ -228,7 +230,7 @@ pub fn create_genesis_block(config: &Config) -> Block { generated: Empty, }, consensus: ConsensusHeader:: { - prev_root: Bytes32::zeroed(), + prev_root, height, time: fuel_core_types::tai64::Tai64::UNIX_EPOCH, generated: Empty, @@ -291,7 +293,7 @@ mod tests { use std::vec; #[tokio::test] - async fn config_initializes_block_height_of_genesic_block() { + async fn config_initializes_block_height_of_genesis_block() { let block_height = BlockHeight::from(99u32); let service_config = Config::local_node_with_state_config(StateConfig { last_block: Some(LastBlockConfig { From d6fa53c292862baacb75306b2225d51035502670 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Tue, 7 May 2024 20:11:22 -0400 Subject: [PATCH 02/34] Update state.rs --- crates/chain-config/src/config/state.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index a8444d36bed..b26b3613041 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -291,6 +291,7 @@ impl crate::Randomize for StateConfig { da_block_height: rng.gen(), consensus_parameters_version: rng.gen(), state_transition_version: rng.gen(), + block_hash: rng.gen(), }), } } From 4ce317534c8e95831215a5d2413a0bd292f08914 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Wed, 8 May 2024 16:38:38 -0400 Subject: [PATCH 03/34] Add `OldFuelBlockMerkleData` and `OldFuelBlockMerkleMetadata` --- crates/fuel-core/src/database/block.rs | 48 ++++++++++- crates/fuel-core/src/graphql_api/storage.rs | 4 + .../fuel-core/src/graphql_api/storage/old.rs | 81 +++++++++++++++++++ .../src/graphql_api/worker_service.rs | 41 ++++++++++ .../fuel-core/src/service/genesis/exporter.rs | 4 + .../fuel-core/src/service/genesis/importer.rs | 6 +- .../src/service/genesis/importer/off_chain.rs | 23 +++++- .../src/structured_storage/merkle_data.rs | 2 + 8 files changed, 206 insertions(+), 3 deletions(-) diff --git a/crates/fuel-core/src/database/block.rs b/crates/fuel-core/src/database/block.rs index cd6f19c5483..77badc2519b 100644 --- a/crates/fuel-core/src/database/block.rs +++ b/crates/fuel-core/src/database/block.rs @@ -3,7 +3,13 @@ use crate::{ database_description::off_chain::OffChain, Database, }, - fuel_core_graphql_api::storage::blocks::FuelBlockIdsToHeights, + fuel_core_graphql_api::storage::{ + blocks::FuelBlockIdsToHeights, + old::{ + OldFuelBlockMerkleData, + OldFuelBlockMerkleMetadata, + }, + }, }; use fuel_core_storage::{ iter::{ @@ -45,6 +51,46 @@ impl Database { .get(id) .map(|v| v.map(|v| v.into_owned())) } + + pub fn block_history_proof( + &self, + message_block_height: &BlockHeight, + commit_block_height: &BlockHeight, + ) -> StorageResult { + if message_block_height > commit_block_height { + Err(anyhow::anyhow!( + "The `message_block_height` is higher than `commit_block_height`" + ))?; + } + + let message_merkle_metadata = self + .storage::() + .get(&DenseMetadataKey::Primary(*message_block_height))? + .ok_or(not_found!(OldFuelBlockMerkleMetadata))?; + + let commit_merkle_metadata = self + .storage::() + .get(&DenseMetadataKey::Primary(*commit_block_height))? + .ok_or(not_found!(OldFuelBlockMerkleMetadata))?; + + let storage = self; + let tree: MerkleTree = + MerkleTree::load(storage, commit_merkle_metadata.version()) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + + let proof_index = message_merkle_metadata + .version() + .checked_sub(1) + .ok_or(anyhow::anyhow!("The count of leafs - messages is zero"))?; + let (_, proof_set) = tree + .prove(proof_index) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + + Ok(MerkleProof { + proof_set, + proof_index, + }) + } } impl Database { diff --git a/crates/fuel-core/src/graphql_api/storage.rs b/crates/fuel-core/src/graphql_api/storage.rs index d97e2363f2f..b20e02e172b 100644 --- a/crates/fuel-core/src/graphql_api/storage.rs +++ b/crates/fuel-core/src/graphql_api/storage.rs @@ -93,6 +93,10 @@ pub enum Column { /// Existence of a key in this column means that the message has been spent. /// See [`SpentMessages`](messages::SpentMessages) SpentMessages = 13, + /// See [`FuelBlockMerkleData`](todo) + OldFuelBlockMerkleData, + /// See [`FuelBlockMerkleMetadata`](todo) + OldFuelBlockMerkleMetadata, } impl Column { diff --git a/crates/fuel-core/src/graphql_api/storage/old.rs b/crates/fuel-core/src/graphql_api/storage/old.rs index a083b55c5f3..19e1da661ce 100644 --- a/crates/fuel-core/src/graphql_api/storage/old.rs +++ b/crates/fuel-core/src/graphql_api/storage/old.rs @@ -13,6 +13,10 @@ use fuel_core_storage::{ raw::Raw, }, structured_storage::TableWithBlueprint, + tables::merkle::{ + DenseMerkleMetadata, + DenseMetadataKey, + }, Mappable, }; use fuel_core_txpool::types::TxId; @@ -21,6 +25,7 @@ use fuel_core_types::{ block::CompressedBlock, consensus::Consensus, }, + fuel_merkle::binary, fuel_tx::Transaction, fuel_types::BlockHeight, }; @@ -52,6 +57,58 @@ fuel_core_storage::basic_storage_tests!( ::Value::default() ); +/// Old block Merkle data from before regenesis. +pub struct OldFuelBlockMerkleData; + +impl Mappable for OldFuelBlockMerkleData { + type Key = u64; + type OwnedKey = Self::Key; + type Value = binary::Primitive; + type OwnedValue = Self::Value; +} + +impl TableWithBlueprint for OldFuelBlockMerkleData { + type Blueprint = Plain, Postcard>; + type Column = super::Column; + + fn column() -> Self::Column { + Self::Column::OldFuelBlockMerkleData + } +} + +#[cfg(test)] +fuel_core_storage::basic_storage_tests!( + OldFuelBlockMerkleData, + ::Key::default(), + ::Value::default() +); + +/// Old block Merkle metadata from before regenesis. +pub struct OldFuelBlockMerkleMetadata; + +impl Mappable for OldFuelBlockMerkleMetadata { + type Key = DenseMetadataKey; + type OwnedKey = Self::Key; + type Value = DenseMerkleMetadata; + type OwnedValue = Self::Value; +} + +impl TableWithBlueprint for OldFuelBlockMerkleMetadata { + type Blueprint = Plain; + type Column = super::Column; + + fn column() -> Self::Column { + Self::Column::OldFuelBlockMerkleData + } +} + +#[cfg(test)] +fuel_core_storage::basic_storage_tests!( + OldFuelBlockMerkleData, + ::Key::default(), + ::Value::default() +); + /// Old blocks from before regenesis. /// Has same form as [`SealedBlockConsensus`](fuel_core_storage::tables::SealedBlockConsensus). pub struct OldFuelBlockConsensus; @@ -141,3 +198,27 @@ impl AddTable for StateConfigBuilder { // Do not include these for now } } + +impl AsTable for StateConfig { + fn as_table(&self) -> Vec> { + Vec::new() // Do not include these for now + } +} + +impl AddTable for StateConfigBuilder { + fn add(&mut self, _entries: Vec>) { + // Do not include these for now + } +} + +impl AsTable for StateConfig { + fn as_table(&self) -> Vec> { + Vec::new() // Do not include these for now + } +} + +impl AddTable for StateConfigBuilder { + fn add(&mut self, _entries: Vec>) { + // Do not include these for now + } +} diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index ad76fda9f3b..cc34728257c 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -14,6 +14,10 @@ use crate::{ OwnedMessageKey, SpentMessages, }, + old::{ + OldFuelBlockMerkleData, + OldFuelBlockMerkleMetadata, + }, }, }, graphql_api::storage::relayed_transactions::RelayedTransactionStatuses, @@ -28,6 +32,10 @@ use fuel_core_services::{ StateWatcher, }; use fuel_core_storage::{ + tables::merkle::{ + DenseMerkleMetadata, + DenseMetadataKey, + }, Result as StorageResult, StorageAsMut, }; @@ -41,6 +49,7 @@ use fuel_core_types::{ consensus::Consensus, }, entities::relayer::transaction::RelayedTransactionStatus, + fuel_merkle::binary, fuel_tx::{ field::{ Inputs, @@ -375,6 +384,38 @@ where Ok(()) } +pub fn copy_to_old_block_merkle_data<'a, I, T>( + block_merkle_data: I, + db: &mut T, +) -> StorageResult<()> +where + I: Iterator, + T: OffChainDatabase, +{ + for (height, block) in block_merkle_data { + let version = **height as u64; + db.storage::() + .insert(&version, block)?; + } + Ok(()) +} + +pub fn copy_to_old_block_merkle_metadata<'a, I, T>( + block_merkle_data: I, + db: &mut T, +) -> StorageResult<()> +where + I: Iterator, + T: OffChainDatabase, +{ + for (height, metadata) in block_merkle_data { + let key = DenseMetadataKey::Primary(*height); + db.storage::() + .insert(&key, metadata)?; + } + Ok(()) +} + pub fn copy_to_old_transactions<'a, I, T>( transactions: I, db: &mut T, diff --git a/crates/fuel-core/src/service/genesis/exporter.rs b/crates/fuel-core/src/service/genesis/exporter.rs index 940ad068db7..264057d7f42 100644 --- a/crates/fuel-core/src/service/genesis/exporter.rs +++ b/crates/fuel-core/src/service/genesis/exporter.rs @@ -13,6 +13,8 @@ use crate::{ }, graphql_api::storage::old::{ OldFuelBlockConsensus, + OldFuelBlockMerkleData, + OldFuelBlockMerkleMetadata, OldFuelBlocks, OldTransactions, }, @@ -113,6 +115,8 @@ where OldFuelBlocks, OldFuelBlockConsensus, OldTransactions, + OldFuelBlockMerkleData, + OldFuelBlockMerkleMetadata, SpentMessages ); diff --git a/crates/fuel-core/src/service/genesis/importer.rs b/crates/fuel-core/src/service/genesis/importer.rs index 178f3b360f8..1960ba845c1 100644 --- a/crates/fuel-core/src/service/genesis/importer.rs +++ b/crates/fuel-core/src/service/genesis/importer.rs @@ -8,7 +8,10 @@ use crate::{ off_chain::OffChain, on_chain::OnChain, }, - fuel_core_graphql_api::storage::messages::SpentMessages, + fuel_core_graphql_api::storage::{ + messages::SpentMessages, + old::OldFuelBlockMerkleData, + }, graphql_api::storage::{ blocks::FuelBlockIdsToHeights, coins::OwnedCoins, @@ -129,6 +132,7 @@ impl SnapshotImporter { self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; + self.spawn_worker_off_chain::()?; self.task_manager.wait().await?; diff --git a/crates/fuel-core/src/service/genesis/importer/off_chain.rs b/crates/fuel-core/src/service/genesis/importer/off_chain.rs index 58cce0dd211..d067133e3e0 100644 --- a/crates/fuel-core/src/service/genesis/importer/off_chain.rs +++ b/crates/fuel-core/src/service/genesis/importer/off_chain.rs @@ -5,7 +5,10 @@ use crate::{ database_description::off_chain::OffChain, GenesisDatabase, }, - fuel_core_graphql_api::storage::messages::SpentMessages, + fuel_core_graphql_api::storage::{ + messages::SpentMessages, + old::OldFuelBlockMerkleData, + }, graphql_api::{ storage::{ blocks::FuelBlockIdsToHeights, @@ -202,6 +205,24 @@ impl ImportTable for Handler { } } +impl ImportTable for Handler { + type TableInSnapshot = OldFuelBlockMerkleData; + type TableBeingWritten = OldFuelBlockMerkleData; + type DbDesc = OffChain; + + fn process( + &mut self, + group: Vec>, + tx: &mut StorageTransaction<&mut GenesisDatabase>, + ) -> anyhow::Result<()> { + let blocks = group + .iter() + .map(|TableEntry { key, value, .. }| (key, value)); + worker_service::copy_to_old_blocks(blocks, tx)?; + Ok(()) + } +} + impl ImportTable for Handler { type TableInSnapshot = SealedBlockConsensus; type TableBeingWritten = OldFuelBlockConsensus; diff --git a/crates/storage/src/structured_storage/merkle_data.rs b/crates/storage/src/structured_storage/merkle_data.rs index a80a6c56a94..cb4710add1d 100644 --- a/crates/storage/src/structured_storage/merkle_data.rs +++ b/crates/storage/src/structured_storage/merkle_data.rs @@ -19,6 +19,8 @@ use crate::{ }, }; +#[allow(missing_docs)] +#[macro_export] macro_rules! merkle_table { ($table:ident) => { merkle_table!($table, Raw); From 7e13d03a9175b2de30fb085658371e9011ebf48b Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Wed, 8 May 2024 19:50:27 -0400 Subject: [PATCH 04/34] Retrieve merkle metadata from archived data --- crates/chain-config/src/config/state.rs | 24 ++++++++++++++ crates/fuel-core/src/graphql_api/database.rs | 21 ++++++++++-- crates/fuel-core/src/graphql_api/ports.rs | 17 +++++++++- .../src/graphql_api/worker_service.rs | 10 +++--- .../src/service/adapters/graphql_api.rs | 30 +++++++++++++++-- .../service/adapters/graphql_api/off_chain.rs | 12 +++++++ .../fuel-core/src/service/genesis/exporter.rs | 6 ++++ .../fuel-core/src/service/genesis/importer.rs | 12 +++++-- .../src/service/genesis/importer/off_chain.rs | 33 ++++++++++++++++--- 9 files changed, 147 insertions(+), 18 deletions(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index b26b3613041..0dd0e5b8e3a 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -49,6 +49,10 @@ use bech32::{ }; #[cfg(feature = "test-helpers")] use core::str::FromStr; +use fuel_core_storage::tables::merkle::{ + FuelBlockMerkleData, + FuelBlockMerkleMetadata, +}; use fuel_core_types::blockchain::header::{ BlockHeader, ConsensusParametersVersion, @@ -438,6 +442,26 @@ impl AddTable for StateConfigBuilder { fn add(&mut self, _entries: Vec>) {} } +impl AsTable for StateConfig { + fn as_table(&self) -> Vec> { + Vec::new() // Do not include these for now + } +} + +impl AddTable for StateConfigBuilder { + fn add(&mut self, _entries: Vec>) {} +} + +impl AsTable for StateConfig { + fn as_table(&self) -> Vec> { + Vec::new() // Do not include these for now + } +} + +impl AddTable for StateConfigBuilder { + fn add(&mut self, _entries: Vec>) {} +} + impl AddTable for StateConfigBuilder { fn add(&mut self, _: Vec>) {} } diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index 5ac6e9b5589..b13f3caab95 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -46,6 +46,7 @@ use fuel_core_types::{ }, transaction::RelayedTransactionStatus, }, + fuel_merkle::binary::Primitive, fuel_tx::{ Address, AssetId, @@ -268,8 +269,13 @@ impl DatabaseMessageProof for ReadView { message_block_height: &BlockHeight, commit_block_height: &BlockHeight, ) -> StorageResult { - self.on_chain - .block_history_proof(message_block_height, commit_block_height) + if *message_block_height >= self.genesis_height { + self.on_chain + .block_history_proof(message_block_height, commit_block_height) + } else { + self.off_chain + .block_history_proof(message_block_height, commit_block_height) + } } } @@ -329,6 +335,17 @@ impl OffChainDatabase for ReadView { self.off_chain.old_blocks(height, direction) } + fn old_block_merkle_data(&self, _version: &u64) -> StorageResult> { + todo!() + } + + fn old_block_merkle_metadata( + &self, + _version: &u64, + ) -> StorageResult> { + todo!() + } + fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { self.off_chain.old_block_consensus(height) } diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 9cd1b4ebc6f..0baa797a293 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -32,6 +32,7 @@ use fuel_core_types::{ }, transaction::RelayedTransactionStatus, }, + fuel_merkle::binary, fuel_tx::{ Bytes32, ConsensusParameters, @@ -61,7 +62,7 @@ use fuel_core_types::{ }; use std::sync::Arc; -pub trait OffChainDatabase: Send + Sync { +pub trait OffChainDatabase: Send + Sync + DatabaseMessageProof { fn block_height(&self, block_id: &BlockId) -> StorageResult; fn tx_status(&self, tx_id: &TxId) -> StorageResult; @@ -97,6 +98,16 @@ pub trait OffChainDatabase: Send + Sync { direction: IterDirection, ) -> BoxedIter<'_, StorageResult>; + fn old_block_merkle_data( + &self, + version: &u64, + ) -> StorageResult>; + + fn old_block_merkle_metadata( + &self, + version: &u64, + ) -> StorageResult>; + fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult; fn old_transaction(&self, id: &TxId) -> StorageResult>; @@ -247,10 +258,12 @@ pub mod worker { OwnedMessageIds, SpentMessages, }, + old::OldFuelBlockMerkleMetadata, }, graphql_api::storage::{ old::{ OldFuelBlockConsensus, + OldFuelBlockMerkleData, OldFuelBlocks, OldTransactions, }, @@ -291,6 +304,8 @@ pub mod worker { + StorageMutate + StorageMutate + StorageMutate + + StorageMutate + + StorageMutate + StorageMutate + StorageMutate + StorageMutate diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index cc34728257c..245d7c6a792 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -389,13 +389,12 @@ pub fn copy_to_old_block_merkle_data<'a, I, T>( db: &mut T, ) -> StorageResult<()> where - I: Iterator, + I: Iterator, T: OffChainDatabase, { for (height, block) in block_merkle_data { - let version = **height as u64; db.storage::() - .insert(&version, block)?; + .insert(&height, block)?; } Ok(()) } @@ -405,13 +404,12 @@ pub fn copy_to_old_block_merkle_metadata<'a, I, T>( db: &mut T, ) -> StorageResult<()> where - I: Iterator, + I: Iterator, &'a DenseMerkleMetadata)>, T: OffChainDatabase, { for (height, metadata) in block_merkle_data { - let key = DenseMetadataKey::Primary(*height); db.storage::() - .insert(&key, metadata)?; + .insert(&height, metadata)?; } Ok(()) } diff --git a/crates/fuel-core/src/service/adapters/graphql_api.rs b/crates/fuel-core/src/service/adapters/graphql_api.rs index 871daa9b66b..e8099b39e41 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api.rs @@ -5,7 +5,13 @@ use super::{ StaticGasPrice, }; use crate::{ - database::Database, + database::{ + database_description::{ + off_chain::OffChain, + on_chain::OnChain, + }, + Database, + }, fuel_core_graphql_api::ports::{ worker, BlockProducerPort, @@ -88,13 +94,31 @@ impl TxPoolPort for TxPoolAdapter { } } -impl DatabaseMessageProof for Database { +impl DatabaseMessageProof for Database { + fn block_history_proof( + &self, + message_block_height: &BlockHeight, + commit_block_height: &BlockHeight, + ) -> StorageResult { + Database::::block_history_proof( + self, + message_block_height, + commit_block_height, + ) + } +} + +impl DatabaseMessageProof for Database { fn block_history_proof( &self, message_block_height: &BlockHeight, commit_block_height: &BlockHeight, ) -> StorageResult { - Database::block_history_proof(self, message_block_height, commit_block_height) + Database::::block_history_proof( + self, + message_block_height, + commit_block_height, + ) } } diff --git a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs index 0b21a5d2043..c904dc7b667 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs @@ -47,6 +47,7 @@ use fuel_core_types::{ primitives::BlockId, }, entities::relayer::transaction::RelayedTransactionStatus, + fuel_merkle::binary::Primitive, fuel_tx::{ Address, Bytes32, @@ -141,6 +142,17 @@ impl OffChainDatabase for Database { .into_boxed() } + fn old_block_merkle_data(&self, _version: &u64) -> StorageResult> { + todo!() + } + + fn old_block_merkle_metadata( + &self, + _version: &u64, + ) -> StorageResult> { + todo!() + } + fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { Ok(self .storage_as_ref::() diff --git a/crates/fuel-core/src/service/genesis/exporter.rs b/crates/fuel-core/src/service/genesis/exporter.rs index 264057d7f42..476038b4813 100644 --- a/crates/fuel-core/src/service/genesis/exporter.rs +++ b/crates/fuel-core/src/service/genesis/exporter.rs @@ -34,6 +34,10 @@ use fuel_core_storage::{ kv_store::StorageColumn, structured_storage::TableWithBlueprint, tables::{ + merkle::{ + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, Coins, ContractsAssets, ContractsLatestUtxo, @@ -103,6 +107,8 @@ where ContractsState, ContractsAssets, FuelBlocks, + FuelBlockMerkleData, + FuelBlockMerkleMetadata, Transactions, SealedBlockConsensus, ProcessedTransactions diff --git a/crates/fuel-core/src/service/genesis/importer.rs b/crates/fuel-core/src/service/genesis/importer.rs index 1960ba845c1..2829fe70f22 100644 --- a/crates/fuel-core/src/service/genesis/importer.rs +++ b/crates/fuel-core/src/service/genesis/importer.rs @@ -10,7 +10,10 @@ use crate::{ }, fuel_core_graphql_api::storage::{ messages::SpentMessages, - old::OldFuelBlockMerkleData, + old::{ + OldFuelBlockMerkleData, + OldFuelBlockMerkleMetadata, + }, }, graphql_api::storage::{ blocks::FuelBlockIdsToHeights, @@ -40,6 +43,10 @@ use fuel_core_storage::{ kv_store::StorageColumn, structured_storage::TableWithBlueprint, tables::{ + merkle::{ + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, Coins, ContractsAssets, ContractsLatestUtxo, @@ -132,7 +139,8 @@ impl SnapshotImporter { self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; - self.spawn_worker_off_chain::()?; + self.spawn_worker_off_chain::()?; + self.spawn_worker_off_chain::()?; self.task_manager.wait().await?; diff --git a/crates/fuel-core/src/service/genesis/importer/off_chain.rs b/crates/fuel-core/src/service/genesis/importer/off_chain.rs index d067133e3e0..f567b4dcf0b 100644 --- a/crates/fuel-core/src/service/genesis/importer/off_chain.rs +++ b/crates/fuel-core/src/service/genesis/importer/off_chain.rs @@ -7,7 +7,10 @@ use crate::{ }, fuel_core_graphql_api::storage::{ messages::SpentMessages, - old::OldFuelBlockMerkleData, + old::{ + OldFuelBlockMerkleData, + OldFuelBlockMerkleMetadata, + }, }, graphql_api::{ storage::{ @@ -31,6 +34,10 @@ use crate::{ use fuel_core_chain_config::TableEntry; use fuel_core_storage::{ tables::{ + merkle::{ + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, Coins, FuelBlocks, Messages, @@ -205,8 +212,8 @@ impl ImportTable for Handler { } } -impl ImportTable for Handler { - type TableInSnapshot = OldFuelBlockMerkleData; +impl ImportTable for Handler { + type TableInSnapshot = FuelBlockMerkleData; type TableBeingWritten = OldFuelBlockMerkleData; type DbDesc = OffChain; @@ -218,7 +225,25 @@ impl ImportTable for Handler { let blocks = group .iter() .map(|TableEntry { key, value, .. }| (key, value)); - worker_service::copy_to_old_blocks(blocks, tx)?; + worker_service::copy_to_old_block_merkle_data(blocks, tx)?; + Ok(()) + } +} + +impl ImportTable for Handler { + type TableInSnapshot = FuelBlockMerkleMetadata; + type TableBeingWritten = OldFuelBlockMerkleMetadata; + type DbDesc = OffChain; + + fn process( + &mut self, + group: Vec>, + tx: &mut StorageTransaction<&mut GenesisDatabase>, + ) -> anyhow::Result<()> { + let blocks = group + .iter() + .map(|TableEntry { key, value, .. }| (key, value)); + worker_service::copy_to_old_block_merkle_metadata(blocks, tx)?; Ok(()) } } From 9d38271c5268604c70c225d9f0676352da44b7d6 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Wed, 8 May 2024 19:58:05 -0400 Subject: [PATCH 05/34] Update CHANGELOG.md --- CHANGELOG.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a958c0222d6..23649d0cfc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,18 +5,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] + ### Changed +- [#1891](https://github.com/FuelLabs/fuel-core/pull/1891): Regenesis now preserves `FuelBlockMerkleData` and `FuelBlockMerkleMetadata` in the off-chain table. These tables are checked when querying message proofs. - [#1886](https://github.com/FuelLabs/fuel-core/pull/1886): Use ref to `Block` in validation code - [#1876](https://github.com/FuelLabs/fuel-core/pull/1876): Updated benchmark to include the worst scenario for `CROO` opcode. Also include consensus parameters in bench output. - -### Changed - - [#1879](https://github.com/FuelLabs/fuel-core/pull/1879): Return the old behaviour for the `discovery_works` test. - [#1848](https://github.com/FuelLabs/fuel-core/pull/1848): Added `version` field to the `Block` and `BlockHeader` GraphQL entities. Added corresponding `version` field to the `Block` and `BlockHeader` client types in `fuel-core-client`. - -### Changed - - [#1873](https://github.com/FuelLabs/fuel-core/pull/1873/): Separate dry runs from block production in executor code, remove `ExecutionKind` and `ExecutionType`, remove `thread_block_transaction` concept, remove `PartialBlockComponent` type, refactor away `inner` functions. ## [Version 0.26.0] From aaa061c14ba874bfd1d56aeeb42c23aaa0980343 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Wed, 8 May 2024 20:02:37 -0400 Subject: [PATCH 06/34] Revert "Populate prev root from last block before regenesis" This reverts commit 72457642702df981714bff727ecd6451aed60e9b. --- crates/chain-config/src/config/state.rs | 3 --- crates/fuel-core/src/service/genesis.rs | 8 +++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index 0dd0e5b8e3a..908fe008ecb 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -93,8 +93,6 @@ pub struct LastBlockConfig { pub consensus_parameters_version: ConsensusParametersVersion, /// The version of state transition function used to produce last block. pub state_transition_version: StateTransitionBytecodeVersion, - /// The block id of the last block - pub block_hash: Bytes32, } impl From for LastBlockConfig { @@ -114,7 +112,6 @@ impl From<&BlockHeader> for LastBlockConfig { state_transition_version: header .application() .state_transition_bytecode_version, - block_hash: header.consensus().prev_root, } } } diff --git a/crates/fuel-core/src/service/genesis.rs b/crates/fuel-core/src/service/genesis.rs index ebaf8d55021..a1b879adf5d 100644 --- a/crates/fuel-core/src/service/genesis.rs +++ b/crates/fuel-core/src/service/genesis.rs @@ -178,7 +178,6 @@ pub fn create_genesis_block(config: &Config) -> Block { let da_height; let consensus_parameters_version; let state_transition_bytecode_version; - let prev_root; // If the rollup continues the old rollup, the height of the new block should // be higher than that of the old chain by one to make it continuous. @@ -197,8 +196,8 @@ pub fn create_genesis_block(config: &Config) -> Block { .state_transition_version .checked_add(1) .expect("State transition bytecode version overflow"); + da_height = latest_block.da_block_height; - prev_root = latest_block.block_hash; } else { height = 0u32.into(); #[cfg(feature = "relayer")] @@ -215,7 +214,6 @@ pub fn create_genesis_block(config: &Config) -> Block { } consensus_parameters_version = ConsensusParametersVersion::MIN; state_transition_bytecode_version = StateTransitionBytecodeVersion::MIN; - prev_root = Bytes32::zeroed(); } let transactions_ids = vec![]; @@ -230,7 +228,7 @@ pub fn create_genesis_block(config: &Config) -> Block { generated: Empty, }, consensus: ConsensusHeader:: { - prev_root, + prev_root: Bytes32::zeroed(), height, time: fuel_core_types::tai64::Tai64::UNIX_EPOCH, generated: Empty, @@ -293,7 +291,7 @@ mod tests { use std::vec; #[tokio::test] - async fn config_initializes_block_height_of_genesis_block() { + async fn config_initializes_block_height_of_genesic_block() { let block_height = BlockHeight::from(99u32); let service_config = Config::local_node_with_state_config(StateConfig { last_block: Some(LastBlockConfig { From e387da68691c4f4ab5324c60d19209f82c85d141 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Wed, 8 May 2024 20:04:51 -0400 Subject: [PATCH 07/34] Update state.rs --- crates/chain-config/src/config/state.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index 908fe008ecb..ead101675d7 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -292,7 +292,6 @@ impl crate::Randomize for StateConfig { da_block_height: rng.gen(), consensus_parameters_version: rng.gen(), state_transition_version: rng.gen(), - block_hash: rng.gen(), }), } } From 689c26748621c8f50472ef10150ac46cb51cc165 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 13:48:13 -0400 Subject: [PATCH 08/34] Update worker_service.rs --- crates/fuel-core/src/graphql_api/worker_service.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index 245d7c6a792..cfe58d78a1d 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -394,22 +394,22 @@ where { for (height, block) in block_merkle_data { db.storage::() - .insert(&height, block)?; + .insert(height, block)?; } Ok(()) } pub fn copy_to_old_block_merkle_metadata<'a, I, T>( - block_merkle_data: I, + block_merkle_metadata: I, db: &mut T, ) -> StorageResult<()> where I: Iterator, &'a DenseMerkleMetadata)>, T: OffChainDatabase, { - for (height, metadata) in block_merkle_data { + for (height, metadata) in block_merkle_metadata { db.storage::() - .insert(&height, metadata)?; + .insert(height, metadata)?; } Ok(()) } From 161aa7ca76f172e77ca1e254054cbc6a9832105d Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 15:02:36 -0400 Subject: [PATCH 09/34] Fix OldFuelBlockMerkleMetadata basic storage test --- crates/fuel-core/src/graphql_api/storage/old.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fuel-core/src/graphql_api/storage/old.rs b/crates/fuel-core/src/graphql_api/storage/old.rs index 19e1da661ce..c4fb56dadba 100644 --- a/crates/fuel-core/src/graphql_api/storage/old.rs +++ b/crates/fuel-core/src/graphql_api/storage/old.rs @@ -104,9 +104,9 @@ impl TableWithBlueprint for OldFuelBlockMerkleMetadata { #[cfg(test)] fuel_core_storage::basic_storage_tests!( - OldFuelBlockMerkleData, - ::Key::default(), - ::Value::default() + OldFuelBlockMerkleMetadata, + ::Key::default(), + ::Value::default() ); /// Old blocks from before regenesis. From 8ba540ad805cdb5f587a0e0c3f9927196d4e0700 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 18:15:20 -0400 Subject: [PATCH 10/34] Fix merkle data and metadata export --- crates/fuel-core/src/graphql_api/storage.rs | 8 ++++---- crates/fuel-core/src/graphql_api/storage/old.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/fuel-core/src/graphql_api/storage.rs b/crates/fuel-core/src/graphql_api/storage.rs index b20e02e172b..13c6dd972d2 100644 --- a/crates/fuel-core/src/graphql_api/storage.rs +++ b/crates/fuel-core/src/graphql_api/storage.rs @@ -93,10 +93,10 @@ pub enum Column { /// Existence of a key in this column means that the message has been spent. /// See [`SpentMessages`](messages::SpentMessages) SpentMessages = 13, - /// See [`FuelBlockMerkleData`](todo) - OldFuelBlockMerkleData, - /// See [`FuelBlockMerkleMetadata`](todo) - OldFuelBlockMerkleMetadata, + /// See [`OldFuelBlockMerkleData`](old::OldFuelBlockMerkleData) + OldFuelBlockMerkleData = 14, + /// See [`OldFuelBlockMerkleMetadata`](old::OldFuelBlockMerkleMetadata) + OldFuelBlockMerkleMetadata = 15, } impl Column { diff --git a/crates/fuel-core/src/graphql_api/storage/old.rs b/crates/fuel-core/src/graphql_api/storage/old.rs index c4fb56dadba..3e5aff82150 100644 --- a/crates/fuel-core/src/graphql_api/storage/old.rs +++ b/crates/fuel-core/src/graphql_api/storage/old.rs @@ -98,7 +98,7 @@ impl TableWithBlueprint for OldFuelBlockMerkleMetadata { type Column = super::Column; fn column() -> Self::Column { - Self::Column::OldFuelBlockMerkleData + Self::Column::OldFuelBlockMerkleMetadata } } From 7d42421c88b94720b30284ef4339acbf13ae644b Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 20:41:29 -0400 Subject: [PATCH 11/34] Refactor DatabaseMessageProof impls --- CHANGELOG.md | 2 +- crates/fuel-core/src/database/block.rs | 98 +------------- crates/fuel-core/src/graphql_api/database.rs | 15 ++- crates/fuel-core/src/graphql_api/ports.rs | 70 +++++++++- .../src/service/adapters/graphql_api.rs | 38 ------ .../service/adapters/graphql_api/off_chain.rs | 124 ++++++++++++++---- .../service/adapters/graphql_api/on_chain.rs | 41 ++++++ 7 files changed, 215 insertions(+), 173 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23649d0cfc9..da55fd3a079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed -- [#1891](https://github.com/FuelLabs/fuel-core/pull/1891): Regenesis now preserves `FuelBlockMerkleData` and `FuelBlockMerkleMetadata` in the off-chain table. These tables are checked when querying message proofs. +- [#1891](https://github.com/FuelLabs/fuel-core/pull/1891): Regenesis now preserves `FuelBlockMerkleData` and `FuelBlockMerkleMetadata` in the off-chain table. These tables are checked when querying message proofs. - [#1886](https://github.com/FuelLabs/fuel-core/pull/1886): Use ref to `Block` in validation code - [#1876](https://github.com/FuelLabs/fuel-core/pull/1876): Updated benchmark to include the worst scenario for `CROO` opcode. Also include consensus parameters in bench output. - [#1879](https://github.com/FuelLabs/fuel-core/pull/1879): Return the old behaviour for the `discovery_works` test. diff --git a/crates/fuel-core/src/database/block.rs b/crates/fuel-core/src/database/block.rs index 77badc2519b..ebbf6ed7d05 100644 --- a/crates/fuel-core/src/database/block.rs +++ b/crates/fuel-core/src/database/block.rs @@ -3,13 +3,7 @@ use crate::{ database_description::off_chain::OffChain, Database, }, - fuel_core_graphql_api::storage::{ - blocks::FuelBlockIdsToHeights, - old::{ - OldFuelBlockMerkleData, - OldFuelBlockMerkleMetadata, - }, - }, + fuel_core_graphql_api::storage::blocks::FuelBlockIdsToHeights, }; use fuel_core_storage::{ iter::{ @@ -18,15 +12,9 @@ use fuel_core_storage::{ }, not_found, tables::{ - merkle::{ - DenseMetadataKey, - FuelBlockMerkleData, - FuelBlockMerkleMetadata, - }, FuelBlocks, Transactions, }, - Error as StorageError, Result as StorageResult, StorageAsRef, }; @@ -38,8 +26,6 @@ use fuel_core_types::{ }, primitives::BlockId, }, - entities::relayer::message::MerkleProof, - fuel_merkle::binary::MerkleTree, fuel_types::BlockHeight, }; use itertools::Itertools; @@ -51,46 +37,6 @@ impl Database { .get(id) .map(|v| v.map(|v| v.into_owned())) } - - pub fn block_history_proof( - &self, - message_block_height: &BlockHeight, - commit_block_height: &BlockHeight, - ) -> StorageResult { - if message_block_height > commit_block_height { - Err(anyhow::anyhow!( - "The `message_block_height` is higher than `commit_block_height`" - ))?; - } - - let message_merkle_metadata = self - .storage::() - .get(&DenseMetadataKey::Primary(*message_block_height))? - .ok_or(not_found!(OldFuelBlockMerkleMetadata))?; - - let commit_merkle_metadata = self - .storage::() - .get(&DenseMetadataKey::Primary(*commit_block_height))? - .ok_or(not_found!(OldFuelBlockMerkleMetadata))?; - - let storage = self; - let tree: MerkleTree = - MerkleTree::load(storage, commit_merkle_metadata.version()) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - - let proof_index = message_merkle_metadata - .version() - .checked_sub(1) - .ok_or(anyhow::anyhow!("The count of leafs - messages is zero"))?; - let (_, proof_set) = tree - .prove(proof_index) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - - Ok(MerkleProof { - proof_set, - proof_index, - }) - } } impl Database { @@ -134,48 +80,6 @@ impl Database { } } -impl Database { - pub fn block_history_proof( - &self, - message_block_height: &BlockHeight, - commit_block_height: &BlockHeight, - ) -> StorageResult { - if message_block_height > commit_block_height { - Err(anyhow::anyhow!( - "The `message_block_height` is higher than `commit_block_height`" - ))?; - } - - let message_merkle_metadata = self - .storage::() - .get(&DenseMetadataKey::Primary(*message_block_height))? - .ok_or(not_found!(FuelBlockMerkleMetadata))?; - - let commit_merkle_metadata = self - .storage::() - .get(&DenseMetadataKey::Primary(*commit_block_height))? - .ok_or(not_found!(FuelBlockMerkleMetadata))?; - - let storage = self; - let tree: MerkleTree = - MerkleTree::load(storage, commit_merkle_metadata.version()) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - - let proof_index = message_merkle_metadata - .version() - .checked_sub(1) - .ok_or(anyhow::anyhow!("The count of leafs - messages is zero"))?; - let (_, proof_set) = tree - .prove(proof_index) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - - Ok(MerkleProof { - proof_set, - proof_index, - }) - } -} - #[allow(clippy::arithmetic_side_effects)] #[cfg(test)] mod tests { diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index b13f3caab95..727d653aaef 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -18,7 +18,10 @@ use fuel_core_storage::{ IterDirection, }, not_found, - tables::Transactions, + tables::{ + merkle::DenseMerkleMetadata, + Transactions, + }, transactional::AtomicView, Error as StorageError, IsNotFound, @@ -335,15 +338,15 @@ impl OffChainDatabase for ReadView { self.off_chain.old_blocks(height, direction) } - fn old_block_merkle_data(&self, _version: &u64) -> StorageResult> { - todo!() + fn old_block_merkle_data(&self, version: &u64) -> StorageResult { + self.off_chain.old_block_merkle_data(version) } fn old_block_merkle_metadata( &self, - _version: &u64, - ) -> StorageResult> { - todo!() + height: &BlockHeight, + ) -> StorageResult { + self.off_chain.old_block_merkle_metadata(height) } fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 0baa797a293..2ce79f14e00 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -6,12 +6,14 @@ use fuel_core_storage::{ IterDirection, }, tables::{ + merkle::DenseMerkleMetadata, Coins, ContractsAssets, ContractsRawCode, Messages, }, Error as StorageError, + Mappable, Result as StorageResult, StorageInspect, }; @@ -98,15 +100,12 @@ pub trait OffChainDatabase: Send + Sync + DatabaseMessageProof { direction: IterDirection, ) -> BoxedIter<'_, StorageResult>; - fn old_block_merkle_data( - &self, - version: &u64, - ) -> StorageResult>; + fn old_block_merkle_data(&self, version: &u64) -> StorageResult; fn old_block_merkle_metadata( &self, - version: &u64, - ) -> StorageResult>; + height: &BlockHeight, + ) -> StorageResult; fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult; @@ -189,6 +188,25 @@ pub trait DatabaseChain { fn da_height(&self) -> StorageResult; } +/// Trait that defines getters for Block Merkle data and metadata +pub trait DatabaseMerkle { + type TableType: Mappable< + Key = u64, + Value = binary::Primitive, + OwnedValue = binary::Primitive, + >; + + fn merkle_data(&self, version: &u64) -> StorageResult; + + fn merkle_metadata(&self, height: &BlockHeight) + -> StorageResult; + + fn load_merkle_tree( + &self, + version: u64, + ) -> StorageResult>; +} + #[async_trait] pub trait TxPoolPort: Send + Sync { fn transaction(&self, id: TxId) -> Option; @@ -236,6 +254,46 @@ pub trait DatabaseMessageProof: Send + Sync { ) -> StorageResult; } +impl DatabaseMessageProof for T +where + T: Send + + Sync + + DatabaseMerkle + + StorageInspect<::TableType, Error = StorageError>, +{ + fn block_history_proof( + &self, + message_block_height: &BlockHeight, + commit_block_height: &BlockHeight, + ) -> StorageResult { + if message_block_height > commit_block_height { + Err(anyhow::anyhow!( + "The `message_block_height` is higher than `commit_block_height`" + ))?; + } + + let message_merkle_metadata = self.merkle_metadata(message_block_height)?; + let commit_merkle_metadata = self.merkle_metadata(commit_block_height)?; + let version = commit_merkle_metadata.version(); + let tree = self + .load_merkle_tree(version) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + + let proof_index = message_merkle_metadata + .version() + .checked_sub(1) + .ok_or(anyhow::anyhow!("The count of leafs - messages is zero"))?; + let (_, proof_set) = tree + .prove(proof_index) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + + Ok(MerkleProof { + proof_set, + proof_index, + }) + } +} + #[async_trait::async_trait] pub trait P2pPort: Send + Sync { async fn all_peer_info(&self) -> anyhow::Result>; diff --git a/crates/fuel-core/src/service/adapters/graphql_api.rs b/crates/fuel-core/src/service/adapters/graphql_api.rs index e8099b39e41..ccaa4c9b1d6 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api.rs @@ -5,18 +5,10 @@ use super::{ StaticGasPrice, }; use crate::{ - database::{ - database_description::{ - off_chain::OffChain, - on_chain::OnChain, - }, - Database, - }, fuel_core_graphql_api::ports::{ worker, BlockProducerPort, ConsensusProvider, - DatabaseMessageProof, GasPriceEstimate, P2pPort, TxPoolPort, @@ -28,13 +20,11 @@ use crate::{ }; use async_trait::async_trait; use fuel_core_services::stream::BoxStream; -use fuel_core_storage::Result as StorageResult; use fuel_core_txpool::{ service::TxStatusMessage, types::TxId, }; use fuel_core_types::{ - entities::relayer::message::MerkleProof, fuel_tx::{ Bytes32, ConsensusParameters, @@ -94,34 +84,6 @@ impl TxPoolPort for TxPoolAdapter { } } -impl DatabaseMessageProof for Database { - fn block_history_proof( - &self, - message_block_height: &BlockHeight, - commit_block_height: &BlockHeight, - ) -> StorageResult { - Database::::block_history_proof( - self, - message_block_height, - commit_block_height, - ) - } -} - -impl DatabaseMessageProof for Database { - fn block_history_proof( - &self, - message_block_height: &BlockHeight, - commit_block_height: &BlockHeight, - ) -> StorageResult { - Database::::block_history_proof( - self, - message_block_height, - commit_block_height, - ) - } -} - #[async_trait] impl BlockProducerPort for BlockProducerAdapter { async fn dry_run_txs( diff --git a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs index c904dc7b667..5a23ecc3567 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs @@ -10,14 +10,22 @@ use crate::{ }, storage::{ contracts::ContractsInfo, + old::OldFuelBlockMerkleMetadata, relayed_transactions::RelayedTransactionStatuses, transactions::OwnedTransactionIndexCursor, }, }, - graphql_api::storage::old::{ - OldFuelBlockConsensus, - OldFuelBlocks, - OldTransactions, + graphql_api::{ + ports::{ + DatabaseBlocks, + DatabaseMerkle, + }, + storage::old::{ + OldFuelBlockConsensus, + OldFuelBlockMerkleData, + OldFuelBlocks, + OldTransactions, + }, }, }; use fuel_core_storage::{ @@ -28,6 +36,10 @@ use fuel_core_storage::{ IteratorOverTable, }, not_found, + tables::merkle::{ + DenseMerkleMetadata, + DenseMetadataKey, + }, transactional::{ IntoTransaction, StorageTransaction, @@ -47,7 +59,7 @@ use fuel_core_types::{ primitives::BlockId, }, entities::relayer::transaction::RelayedTransactionStatus, - fuel_merkle::binary::Primitive, + fuel_merkle::binary, fuel_tx::{ Address, Bytes32, @@ -63,6 +75,80 @@ use fuel_core_types::{ services::txpool::TransactionStatus, }; +use std::borrow::Cow; + +impl DatabaseBlocks for Database { + fn transaction(&self, tx_id: &TxId) -> StorageResult { + self.storage_as_ref::() + .get(tx_id)? + .map(Cow::into_owned) + .ok_or(not_found!(OldTransactions)) + } + + fn block(&self, height: &BlockHeight) -> StorageResult { + self.storage_as_ref::() + .get(height)? + .map(Cow::into_owned) + .ok_or(not_found!(OldFuelBlocks)) + } + + fn blocks( + &self, + height: Option, + direction: IterDirection, + ) -> BoxedIter<'_, StorageResult> { + self.iter_all_by_start::(height.as_ref(), Some(direction)) + .map(|r| r.map(|(_, block)| block)) + .into_boxed() + } + + fn latest_height(&self) -> StorageResult { + self.iter_all::(Some(IterDirection::Reverse)) + .next() + .transpose()? + .map(|(height, _)| height) + .ok_or(not_found!("BlockHeight")) + } + + fn consensus(&self, height: &BlockHeight) -> StorageResult { + self.storage_as_ref::() + .get(height)? + .map(Cow::into_owned) + .ok_or(not_found!(OldFuelBlockConsensus)) + } +} + +impl DatabaseMerkle for Database { + type TableType = OldFuelBlockMerkleData; + + fn merkle_data(&self, version: &u64) -> StorageResult { + self.storage_as_ref::() + .get(version)? + .map(Cow::into_owned) + .ok_or(not_found!(OldFuelBlockMerkleData)) + } + + fn merkle_metadata( + &self, + height: &BlockHeight, + ) -> StorageResult { + self.storage_as_ref::() + .get(&DenseMetadataKey::Primary(*height))? + .map(Cow::into_owned) + .ok_or(not_found!(OldFuelBlockMerkleMetadata)) + } + + fn load_merkle_tree( + &self, + version: u64, + ) -> StorageResult> { + let tree: binary::MerkleTree = + binary::MerkleTree::load(self, version) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + Ok(tree) + } +} + impl OffChainDatabase for Database { fn block_height(&self, id: &BlockId) -> StorageResult { self.get_block_height(id) @@ -123,13 +209,7 @@ impl OffChainDatabase for Database { } fn old_block(&self, height: &BlockHeight) -> StorageResult { - let block = self - .storage_as_ref::() - .get(height)? - .ok_or(not_found!(OldFuelBlocks))? - .into_owned(); - - Ok(block) + ::block(self, height) } fn old_blocks( @@ -137,28 +217,22 @@ impl OffChainDatabase for Database { height: Option, direction: IterDirection, ) -> BoxedIter<'_, StorageResult> { - self.iter_all_by_start::(height.as_ref(), Some(direction)) - .map(|r| r.map(|(_, block)| block)) - .into_boxed() + ::blocks(self, height, direction) } - fn old_block_merkle_data(&self, _version: &u64) -> StorageResult> { - todo!() + fn old_block_merkle_data(&self, version: &u64) -> StorageResult { + ::merkle_data(self, version) } fn old_block_merkle_metadata( &self, - _version: &u64, - ) -> StorageResult> { - todo!() + height: &BlockHeight, + ) -> StorageResult { + ::merkle_metadata(self, height) } fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { - Ok(self - .storage_as_ref::() - .get(height)? - .ok_or(not_found!(OldFuelBlockConsensus))? - .into_owned()) + ::consensus(self, height) } fn old_transaction(&self, id: &TxId) -> StorageResult> { diff --git a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs index 7f845ce7731..cd9692e7f84 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs @@ -7,6 +7,7 @@ use crate::{ DatabaseMessages, OnChainDatabase, }, + graphql_api::ports::DatabaseMerkle, }; use fuel_core_importer::ports::ImporterDatabase; use fuel_core_storage::{ @@ -18,6 +19,12 @@ use fuel_core_storage::{ }, not_found, tables::{ + merkle::{ + DenseMerkleMetadata, + DenseMetadataKey, + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, FuelBlocks, SealedBlockConsensus, Transactions, @@ -37,6 +44,7 @@ use fuel_core_types::{ primitives::DaBlockHeight, }, entities::relayer::message::Message, + fuel_merkle::binary, fuel_tx::{ AssetId, Transaction, @@ -47,7 +55,9 @@ use fuel_core_types::{ }, services::graphql_api::ContractBalance, }; + use itertools::Itertools; +use std::borrow::Cow; impl DatabaseBlocks for Database { fn transaction(&self, tx_id: &TxId) -> StorageResult { @@ -92,6 +102,37 @@ impl DatabaseBlocks for Database { } } +impl DatabaseMerkle for Database { + type TableType = FuelBlockMerkleData; + + fn merkle_data(&self, version: &u64) -> StorageResult { + self.storage::() + .get(&version)? + .map(Cow::into_owned) + .ok_or(not_found!(FuelBlockMerkleData)) + } + + fn merkle_metadata( + &self, + height: &BlockHeight, + ) -> StorageResult { + self.storage::() + .get(&DenseMetadataKey::Primary(*height))? + .map(Cow::into_owned) + .ok_or(not_found!(FuelBlockMerkleMetadata)) + } + + fn load_merkle_tree( + &self, + version: u64, + ) -> StorageResult> { + let tree: binary::MerkleTree = + binary::MerkleTree::load(self, version) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + Ok(tree) + } +} + impl DatabaseMessages for Database { fn all_messages( &self, From e5415c74031ccfe96ec7475fa4a79622b25b2baa Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 20:43:59 -0400 Subject: [PATCH 12/34] Revet macro export --- crates/storage/src/structured_storage/merkle_data.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/storage/src/structured_storage/merkle_data.rs b/crates/storage/src/structured_storage/merkle_data.rs index cb4710add1d..a80a6c56a94 100644 --- a/crates/storage/src/structured_storage/merkle_data.rs +++ b/crates/storage/src/structured_storage/merkle_data.rs @@ -19,8 +19,6 @@ use crate::{ }, }; -#[allow(missing_docs)] -#[macro_export] macro_rules! merkle_table { ($table:ident) => { merkle_table!($table, Raw); From 210c86bf7185f3560779f984aabbb9106d06b036 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 21:00:47 -0400 Subject: [PATCH 13/34] Fix --- crates/fuel-core/src/database/block.rs | 3 ++- crates/fuel-core/src/graphql_api/database.rs | 17 +---------------- crates/fuel-core/src/graphql_api/ports.rs | 7 ------- .../service/adapters/graphql_api/off_chain.rs | 11 ----------- 4 files changed, 3 insertions(+), 35 deletions(-) diff --git a/crates/fuel-core/src/database/block.rs b/crates/fuel-core/src/database/block.rs index ebbf6ed7d05..3c4fe5a6450 100644 --- a/crates/fuel-core/src/database/block.rs +++ b/crates/fuel-core/src/database/block.rs @@ -3,7 +3,7 @@ use crate::{ database_description::off_chain::OffChain, Database, }, - fuel_core_graphql_api::storage::blocks::FuelBlockIdsToHeights, + graphql_api::storage::blocks::FuelBlockIdsToHeights, }; use fuel_core_storage::{ iter::{ @@ -84,6 +84,7 @@ impl Database { #[cfg(test)] mod tests { use super::*; + use crate::graphql_api::ports::DatabaseMessageProof; use fuel_core_storage::StorageMutate; use fuel_core_types::{ blockchain::{ diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index 727d653aaef..9968d08bcce 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -18,10 +18,7 @@ use fuel_core_storage::{ IterDirection, }, not_found, - tables::{ - merkle::DenseMerkleMetadata, - Transactions, - }, + tables::Transactions, transactional::AtomicView, Error as StorageError, IsNotFound, @@ -49,7 +46,6 @@ use fuel_core_types::{ }, transaction::RelayedTransactionStatus, }, - fuel_merkle::binary::Primitive, fuel_tx::{ Address, AssetId, @@ -338,17 +334,6 @@ impl OffChainDatabase for ReadView { self.off_chain.old_blocks(height, direction) } - fn old_block_merkle_data(&self, version: &u64) -> StorageResult { - self.off_chain.old_block_merkle_data(version) - } - - fn old_block_merkle_metadata( - &self, - height: &BlockHeight, - ) -> StorageResult { - self.off_chain.old_block_merkle_metadata(height) - } - fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { self.off_chain.old_block_consensus(height) } diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 2ce79f14e00..d10dc37b385 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -100,13 +100,6 @@ pub trait OffChainDatabase: Send + Sync + DatabaseMessageProof { direction: IterDirection, ) -> BoxedIter<'_, StorageResult>; - fn old_block_merkle_data(&self, version: &u64) -> StorageResult; - - fn old_block_merkle_metadata( - &self, - height: &BlockHeight, - ) -> StorageResult; - fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult; fn old_transaction(&self, id: &TxId) -> StorageResult>; diff --git a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs index 5a23ecc3567..06bb17ad522 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs @@ -220,17 +220,6 @@ impl OffChainDatabase for Database { ::blocks(self, height, direction) } - fn old_block_merkle_data(&self, version: &u64) -> StorageResult { - ::merkle_data(self, version) - } - - fn old_block_merkle_metadata( - &self, - height: &BlockHeight, - ) -> StorageResult { - ::merkle_metadata(self, height) - } - fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { ::consensus(self, height) } From 301e32b67817b5dbd6d978835897e3155f5c68c8 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Thu, 9 May 2024 21:04:47 -0400 Subject: [PATCH 14/34] clippy --- crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs index cd9692e7f84..7147fb408fb 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs @@ -107,7 +107,7 @@ impl DatabaseMerkle for Database { fn merkle_data(&self, version: &u64) -> StorageResult { self.storage::() - .get(&version)? + .get(version)? .map(Cow::into_owned) .ok_or(not_found!(FuelBlockMerkleData)) } From 0a6068b927689f0d8d9da74f2e8f38c68ae9687d Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Fri, 10 May 2024 16:20:15 -0400 Subject: [PATCH 15/34] Test message proofs are preserverd --- tests/tests/regenesis.rs | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index c220b9737fa..977eb7b0d31 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -22,9 +22,16 @@ use fuel_core_client::client::{ FuelClient, }; use fuel_core_types::{ + fuel_asm::{ + op, + GTFArgs, + RegId, + }, + fuel_crypto::PublicKey, fuel_tx::*, fuel_vm::*, }; +use itertools::Itertools; use rand::{ rngs::StdRng, Rng, @@ -382,3 +389,93 @@ async fn test_regenesis_processed_transactions_are_preserved() -> anyhow::Result Ok(()) } + +#[tokio::test(flavor = "multi_thread")] +async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { + let mut rng = StdRng::seed_from_u64(1234); + let core = FuelCoreDriver::spawn(&["--debug", "--poa-instant", "true"]).await?; + + let secret = SecretKey::random(&mut rng); + let public_key: PublicKey = (&secret).into(); + let address = Input::owner(&public_key); + let script_data = [address.to_vec(), 100u64.to_be_bytes().to_vec()] + .into_iter() + .flatten() + .collect_vec(); + let script: Vec = vec![ + op::gtf(0x10, 0x00, GTFArgs::ScriptData.into()), + op::addi(0x11, 0x10, Bytes32::LEN as u16), + op::lw(0x11, 0x11, 0), + op::smo(0x10, 0x00, 0x00, 0x11), + op::ret(RegId::ONE), + ] + .into_iter() + .collect(); + + // Given + let tx = TransactionBuilder::script(script, script_data) + .add_unsigned_coin_input( + secret, + rng.gen(), + 100_000_000, + Default::default(), + Default::default(), + ) + .add_output(Output::change( + Default::default(), + Default::default(), + Default::default(), + )) + .max_fee_limit(1_000_000) + .script_gas_limit(1_000_000) + .finalize_as_transaction(); + + let tx_id = tx.id(&Default::default()); + + let status = core.client.submit_and_await_commit(&tx).await.unwrap(); + let block_height = match status { + TransactionStatus::Success { block_height, .. } => block_height, + _ => panic!("Failed to submit transaction"), + }; + let block_height = block_height + .succ() + .expect("Unable to increment block height"); + + // When + let db_dir = core.kill().await; + + // ------------------------- The genesis node is stopped ------------------------- + + // Take a snapshot + let snapshot_dir = tempdir().expect("Failed to create temp dir"); + take_snapshot(&db_dir, &snapshot_dir) + .await + .expect("Failed to take first snapshot"); + + // ------------------------- Start a node with the regenesis ------------------------- + + let core = FuelCoreDriver::spawn(&[ + "--debug", + "--poa-instant", + "true", + "--snapshot", + snapshot_dir.path().to_str().unwrap(), + ]) + .await?; + let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); + let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); + + // Then + assert_eq!(nonces.len(), 1); + + for nonce in nonces { + let proof = core + .client + .message_proof(&tx_id, &nonce, None, Some(block_height)) + .await + .unwrap(); + assert!(proof.is_some()); + } + + Ok(()) +} From 932fa6beb59866b3c43e138245355c5daab42ffb Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Fri, 10 May 2024 16:31:34 -0400 Subject: [PATCH 16/34] clipheehee --- tests/tests/regenesis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 977eb7b0d31..d08ccce7a33 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -471,7 +471,7 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { for nonce in nonces { let proof = core .client - .message_proof(&tx_id, &nonce, None, Some(block_height)) + .message_proof(&tx_id, nonce, None, Some(block_height)) .await .unwrap(); assert!(proof.is_some()); From 588806392b024e77a1388ae21507e40300071888 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Fri, 10 May 2024 16:43:27 -0400 Subject: [PATCH 17/34] Naming --- crates/fuel-core/src/graphql_api/ports.rs | 22 ++++++++++--------- .../service/adapters/graphql_api/off_chain.rs | 10 ++++----- .../service/adapters/graphql_api/on_chain.rs | 10 ++++----- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index d10dc37b385..9596e86b1e7 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -182,19 +182,21 @@ pub trait DatabaseChain { } /// Trait that defines getters for Block Merkle data and metadata -pub trait DatabaseMerkle { +pub trait DatabaseMerklizedBlocks { type TableType: Mappable< Key = u64, Value = binary::Primitive, OwnedValue = binary::Primitive, >; - fn merkle_data(&self, version: &u64) -> StorageResult; + fn block_merkle_data(&self, version: &u64) -> StorageResult; - fn merkle_metadata(&self, height: &BlockHeight) - -> StorageResult; + fn block_merkle_metadata( + &self, + height: &BlockHeight, + ) -> StorageResult; - fn load_merkle_tree( + fn load_block_merkle_tree( &self, version: u64, ) -> StorageResult>; @@ -251,8 +253,8 @@ impl DatabaseMessageProof for T where T: Send + Sync - + DatabaseMerkle - + StorageInspect<::TableType, Error = StorageError>, + + DatabaseMerklizedBlocks + + StorageInspect<::TableType, Error = StorageError>, { fn block_history_proof( &self, @@ -265,11 +267,11 @@ where ))?; } - let message_merkle_metadata = self.merkle_metadata(message_block_height)?; - let commit_merkle_metadata = self.merkle_metadata(commit_block_height)?; + let message_merkle_metadata = self.block_merkle_metadata(message_block_height)?; + let commit_merkle_metadata = self.block_merkle_metadata(commit_block_height)?; let version = commit_merkle_metadata.version(); let tree = self - .load_merkle_tree(version) + .load_block_merkle_tree(version) .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; let proof_index = message_merkle_metadata diff --git a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs index 06bb17ad522..94095632f3f 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs @@ -18,7 +18,7 @@ use crate::{ graphql_api::{ ports::{ DatabaseBlocks, - DatabaseMerkle, + DatabaseMerklizedBlocks, }, storage::old::{ OldFuelBlockConsensus, @@ -118,17 +118,17 @@ impl DatabaseBlocks for Database { } } -impl DatabaseMerkle for Database { +impl DatabaseMerklizedBlocks for Database { type TableType = OldFuelBlockMerkleData; - fn merkle_data(&self, version: &u64) -> StorageResult { + fn block_merkle_data(&self, version: &u64) -> StorageResult { self.storage_as_ref::() .get(version)? .map(Cow::into_owned) .ok_or(not_found!(OldFuelBlockMerkleData)) } - fn merkle_metadata( + fn block_merkle_metadata( &self, height: &BlockHeight, ) -> StorageResult { @@ -138,7 +138,7 @@ impl DatabaseMerkle for Database { .ok_or(not_found!(OldFuelBlockMerkleMetadata)) } - fn load_merkle_tree( + fn load_block_merkle_tree( &self, version: u64, ) -> StorageResult> { diff --git a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs index 7147fb408fb..bf626bed64b 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs @@ -7,7 +7,7 @@ use crate::{ DatabaseMessages, OnChainDatabase, }, - graphql_api::ports::DatabaseMerkle, + graphql_api::ports::DatabaseMerklizedBlocks, }; use fuel_core_importer::ports::ImporterDatabase; use fuel_core_storage::{ @@ -102,17 +102,17 @@ impl DatabaseBlocks for Database { } } -impl DatabaseMerkle for Database { +impl DatabaseMerklizedBlocks for Database { type TableType = FuelBlockMerkleData; - fn merkle_data(&self, version: &u64) -> StorageResult { + fn block_merkle_data(&self, version: &u64) -> StorageResult { self.storage::() .get(version)? .map(Cow::into_owned) .ok_or(not_found!(FuelBlockMerkleData)) } - fn merkle_metadata( + fn block_merkle_metadata( &self, height: &BlockHeight, ) -> StorageResult { @@ -122,7 +122,7 @@ impl DatabaseMerkle for Database { .ok_or(not_found!(FuelBlockMerkleMetadata)) } - fn load_merkle_tree( + fn load_block_merkle_tree( &self, version: u64, ) -> StorageResult> { From 9cdebb64aee95f5e5e71f3b658418a4d7083972a Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 11:30:27 -0400 Subject: [PATCH 18/34] Update test --- tests/tests/regenesis.rs | 104 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index d08ccce7a33..8bffc28197f 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -27,8 +27,15 @@ use fuel_core_types::{ GTFArgs, RegId, }, - fuel_crypto::PublicKey, - fuel_tx::*, + fuel_crypto::{ + Hasher, + PublicKey, + }, + fuel_merkle, + fuel_tx::{ + input::message::compute_message_id, + *, + }, fuel_vm::*, }; use itertools::Itertools; @@ -37,6 +44,7 @@ use rand::{ Rng, SeedableRng, }; +use std::ops::Deref; use tempfile::{ tempdir, TempDir, @@ -468,14 +476,102 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { // Then assert_eq!(nonces.len(), 1); + // Get the receipts from the contract call. + let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); + + // Get the message id from the receipts. + let message_ids: Vec<_> = receipts.iter().filter_map(|r| r.message_id()).collect(); + for nonce in nonces { - let proof = core + let result = core .client .message_proof(&tx_id, nonce, None, Some(block_height)) .await .unwrap(); - assert!(proof.is_some()); + assert!(result.is_some()); + let result = result.unwrap(); + + // 1. Generate the message id (message fields) + // Produce message id. + let generated_message_id = compute_message_id( + &result.sender, + &result.recipient, + &result.nonce, + result.amount, + &result.data, + ); + + // 2. Generate the block id. (full header) + let mut hasher = Hasher::default(); + hasher.input(result.message_block_header.prev_root.as_ref()); + hasher.input(&result.message_block_header.height.to_be_bytes()[..]); + hasher.input(result.message_block_header.time.0.to_be_bytes()); + hasher.input(result.message_block_header.application_hash.as_ref()); + let message_block_id = hasher.digest(); + assert_eq!(message_block_id, result.message_block_header.id); + + // 3. Verify the message proof. (message receipt root, message id, proof index, proof set, num message receipts in the block) + let message_proof_index = result.message_proof.proof_index; + let message_proof_set: Vec<_> = result + .message_proof + .proof_set + .iter() + .cloned() + .map(Bytes32::from) + .collect(); + assert!(verify_merkle( + result.message_block_header.message_outbox_root, + &generated_message_id, + message_proof_index, + &message_proof_set, + result.message_block_header.message_receipt_count as u64, + )); + + // Generate a proof to compare + let mut tree = fuel_merkle::binary::in_memory::MerkleTree::new(); + for id in &message_ids { + tree.push(id.as_ref()); + } + let (expected_root, expected_set) = tree.prove(message_proof_index).unwrap(); + let expected_set: Vec<_> = expected_set.into_iter().map(Bytes32::from).collect(); + + assert_eq!(message_proof_set, expected_set); + + // Check the root matches the proof and the root on the header. + assert_eq!( + <[u8; 32]>::from(result.message_block_header.message_outbox_root), + expected_root + ); + + // 4. Verify the block proof. (prev_root, block id, proof index, proof set, block count) + let block_proof_index = result.block_proof.proof_index; + let block_proof_set: Vec<_> = result + .block_proof + .proof_set + .iter() + .cloned() + .map(Bytes32::from) + .collect(); + let blocks_count = result.commit_block_header.height; + assert!(verify_merkle( + result.commit_block_header.prev_root, + &message_block_id, + block_proof_index, + &block_proof_set, + blocks_count as u64, + )); } Ok(()) } + +fn verify_merkle>( + root: Bytes32, + data: &D, + index: u64, + set: &[Bytes32], + leaf_count: u64, +) -> bool { + let set: Vec<_> = set.iter().map(|bytes| *bytes.deref()).collect(); + fuel_merkle::binary::verify(root.deref(), data, &set, index, leaf_count) +} From 16e6d0d62414c2f9e31cc3e19f632364d5e174b4 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 12:13:10 -0400 Subject: [PATCH 19/34] Update test --- tests/tests/regenesis.rs | 51 ++++++++++++---------------------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 8bffc28197f..9e91604dd1e 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -31,7 +31,7 @@ use fuel_core_types::{ Hasher, PublicKey, }, - fuel_merkle, + fuel_merkle::binary, fuel_tx::{ input::message::compute_message_id, *, @@ -440,14 +440,9 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { let tx_id = tx.id(&Default::default()); - let status = core.client.submit_and_await_commit(&tx).await.unwrap(); - let block_height = match status { - TransactionStatus::Success { block_height, .. } => block_height, - _ => panic!("Failed to submit transaction"), - }; - let block_height = block_height - .succ() - .expect("Unable to increment block height"); + core.client.submit_and_await_commit(&tx).await.unwrap(); + + let block_height = core.client.produce_blocks(1, None).await.unwrap(); // When let db_dir = core.kill().await; @@ -470,17 +465,15 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { snapshot_dir.path().to_str().unwrap(), ]) .await?; + let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); + let message_ids: Vec<_> = receipts.iter().filter_map(|r| r.message_id()).collect(); let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); // Then assert_eq!(nonces.len(), 1); - // Get the receipts from the contract call. - let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); - // Get the message id from the receipts. - let message_ids: Vec<_> = receipts.iter().filter_map(|r| r.message_id()).collect(); for nonce in nonces { let result = core @@ -516,24 +509,22 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { .message_proof .proof_set .iter() - .cloned() - .map(Bytes32::from) + .map(|bytes| *bytes.deref()) .collect(); - assert!(verify_merkle( - result.message_block_header.message_outbox_root, + assert!(binary::verify( + &*result.message_block_header.message_outbox_root, &generated_message_id, - message_proof_index, &message_proof_set, + message_proof_index, result.message_block_header.message_receipt_count as u64, )); // Generate a proof to compare - let mut tree = fuel_merkle::binary::in_memory::MerkleTree::new(); + let mut tree = binary::in_memory::MerkleTree::new(); for id in &message_ids { tree.push(id.as_ref()); } let (expected_root, expected_set) = tree.prove(message_proof_index).unwrap(); - let expected_set: Vec<_> = expected_set.into_iter().map(Bytes32::from).collect(); assert_eq!(message_proof_set, expected_set); @@ -549,29 +540,17 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { .block_proof .proof_set .iter() - .cloned() - .map(Bytes32::from) + .map(|bytes| *bytes.deref()) .collect(); let blocks_count = result.commit_block_header.height; - assert!(verify_merkle( - result.commit_block_header.prev_root, + assert!(binary::verify( + &*result.commit_block_header.prev_root, &message_block_id, - block_proof_index, &block_proof_set, + block_proof_index, blocks_count as u64, )); } Ok(()) } - -fn verify_merkle>( - root: Bytes32, - data: &D, - index: u64, - set: &[Bytes32], - leaf_count: u64, -) -> bool { - let set: Vec<_> = set.iter().map(|bytes| *bytes.deref()).collect(); - fuel_merkle::binary::verify(root.deref(), data, &set, index, leaf_count) -} From 7fad4608a0458f806713d7ee7f2df8360367989f Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 12:14:20 -0400 Subject: [PATCH 20/34] Fix checks --- crates/fuel-core/src/graphql_api/ports.rs | 2 +- tests/tests/regenesis.rs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index 9596e86b1e7..d53b608dae6 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -277,7 +277,7 @@ where let proof_index = message_merkle_metadata .version() .checked_sub(1) - .ok_or(anyhow::anyhow!("The count of leafs - messages is zero"))?; + .ok_or(anyhow::anyhow!("The count of leaves - messages is zero"))?; let (_, proof_set) = tree .prove(proof_index) .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 9e91604dd1e..48f961fc2e1 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -473,8 +473,6 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { // Then assert_eq!(nonces.len(), 1); - // Get the message id from the receipts. - for nonce in nonces { let result = core .client From 726aad8b5ecf5a17c2db393b05c645de48700dc1 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 12:17:23 -0400 Subject: [PATCH 21/34] block hash Reapply "Populate prev root from last block before regenesis" This reverts commit aaa061c14ba874bfd1d56aeeb42c23aaa0980343. --- crates/chain-config/src/config/state.rs | 4 ++++ crates/fuel-core/src/service/genesis.rs | 8 +++++--- tests/tests/snapshot.rs | 4 ++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index ead101675d7..0dd0e5b8e3a 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -93,6 +93,8 @@ pub struct LastBlockConfig { pub consensus_parameters_version: ConsensusParametersVersion, /// The version of state transition function used to produce last block. pub state_transition_version: StateTransitionBytecodeVersion, + /// The block id of the last block + pub block_hash: Bytes32, } impl From for LastBlockConfig { @@ -112,6 +114,7 @@ impl From<&BlockHeader> for LastBlockConfig { state_transition_version: header .application() .state_transition_bytecode_version, + block_hash: header.consensus().prev_root, } } } @@ -292,6 +295,7 @@ impl crate::Randomize for StateConfig { da_block_height: rng.gen(), consensus_parameters_version: rng.gen(), state_transition_version: rng.gen(), + block_hash: rng.gen(), }), } } diff --git a/crates/fuel-core/src/service/genesis.rs b/crates/fuel-core/src/service/genesis.rs index a1b879adf5d..ebaf8d55021 100644 --- a/crates/fuel-core/src/service/genesis.rs +++ b/crates/fuel-core/src/service/genesis.rs @@ -178,6 +178,7 @@ pub fn create_genesis_block(config: &Config) -> Block { let da_height; let consensus_parameters_version; let state_transition_bytecode_version; + let prev_root; // If the rollup continues the old rollup, the height of the new block should // be higher than that of the old chain by one to make it continuous. @@ -196,8 +197,8 @@ pub fn create_genesis_block(config: &Config) -> Block { .state_transition_version .checked_add(1) .expect("State transition bytecode version overflow"); - da_height = latest_block.da_block_height; + prev_root = latest_block.block_hash; } else { height = 0u32.into(); #[cfg(feature = "relayer")] @@ -214,6 +215,7 @@ pub fn create_genesis_block(config: &Config) -> Block { } consensus_parameters_version = ConsensusParametersVersion::MIN; state_transition_bytecode_version = StateTransitionBytecodeVersion::MIN; + prev_root = Bytes32::zeroed(); } let transactions_ids = vec![]; @@ -228,7 +230,7 @@ pub fn create_genesis_block(config: &Config) -> Block { generated: Empty, }, consensus: ConsensusHeader:: { - prev_root: Bytes32::zeroed(), + prev_root, height, time: fuel_core_types::tai64::Tai64::UNIX_EPOCH, generated: Empty, @@ -291,7 +293,7 @@ mod tests { use std::vec; #[tokio::test] - async fn config_initializes_block_height_of_genesic_block() { + async fn config_initializes_block_height_of_genesis_block() { let block_height = BlockHeight::from(99u32); let service_config = Config::local_node_with_state_config(StateConfig { last_block: Some(LastBlockConfig { diff --git a/tests/tests/snapshot.rs b/tests/tests/snapshot.rs index 3f9bf325eda..f3b19ee1a44 100644 --- a/tests/tests/snapshot.rs +++ b/tests/tests/snapshot.rs @@ -13,6 +13,7 @@ use fuel_core::{ use fuel_core_types::blockchain::primitives::DaBlockHeight; use rand::{ rngs::StdRng, + Rng, SeedableRng, }; @@ -20,6 +21,7 @@ use rand::{ async fn loads_snapshot() { let mut rng = StdRng::seed_from_u64(1234); let db = CombinedDatabase::default(); + let block_hash = rng.gen(); // setup config let starting_state = StateConfig { @@ -28,6 +30,7 @@ async fn loads_snapshot() { da_block_height: DaBlockHeight(u64::MAX), consensus_parameters_version: u32::MAX - 1, state_transition_version: u32::MAX - 1, + block_hash, }), ..StateConfig::randomize(&mut rng) }; @@ -45,6 +48,7 @@ async fn loads_snapshot() { da_block_height: DaBlockHeight(u64::MAX), consensus_parameters_version: u32::MAX, state_transition_version: u32::MAX, + block_hash, }); // initial state From de5e03cefbba7d71e92ea434983382474ac6dd00 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 12:20:48 -0400 Subject: [PATCH 22/34] Clippy --- tests/tests/regenesis.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 48f961fc2e1..3f81c0834d5 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -510,7 +510,7 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { .map(|bytes| *bytes.deref()) .collect(); assert!(binary::verify( - &*result.message_block_header.message_outbox_root, + &result.message_block_header.message_outbox_root, &generated_message_id, &message_proof_set, message_proof_index, @@ -542,7 +542,7 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { .collect(); let blocks_count = result.commit_block_header.height; assert!(binary::verify( - &*result.commit_block_header.prev_root, + &result.commit_block_header.prev_root, &message_block_id, &block_proof_set, block_proof_index, From 3f9f73cdd6024c1bde06fd47f63b9abcd981a44d Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 12:26:11 -0400 Subject: [PATCH 23/34] Update state.rs --- crates/chain-config/src/config/state.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index 0dd0e5b8e3a..1c461b0a060 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -29,7 +29,10 @@ use fuel_core_storage::{ use fuel_core_types::{ blockchain::primitives::DaBlockHeight, entities::contract::ContractUtxoInfo, - fuel_types::BlockHeight, + fuel_types::{ + BlockHeight, + Bytes32, + }, }; use itertools::Itertools; use serde::{ @@ -61,7 +64,6 @@ use fuel_core_types::blockchain::header::{ #[cfg(feature = "test-helpers")] use fuel_core_types::{ fuel_types::Address, - fuel_types::Bytes32, fuel_vm::SecretKey, }; From 470abde22a15d40c9f769f382396fd752d51d940 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 12:34:37 -0400 Subject: [PATCH 24/34] Update snapshot --- crates/chain-config/src/config/state.rs | 2 ++ ..._state__writer__tests__json_snapshot_is_human_readable.snap | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index 1c461b0a060..f6962746be2 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -789,11 +789,13 @@ mod tests { let da_block_height = 14u64.into(); let consensus_parameters_version = 321u32; let state_transition_version = 123u32; + let block_hash = Bytes32::default(); let block_config = LastBlockConfig { block_height, da_block_height, consensus_parameters_version, state_transition_version, + block_hash, }; let writer = writer(temp_dir.path()); diff --git a/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap b/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap index ac94c65db21..263ea01a72b 100644 --- a/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap +++ b/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap @@ -87,6 +87,7 @@ expression: encoded_json "block_height": 2346951900, "da_block_height": 14074420184374977699, "consensus_parameters_version": 2019076799, - "state_transition_version": 1670454246 + "state_transition_version": 1670454246, + "block_hash": "dfa3ac8a57ea08860870fd515cf7ca6afb887dd1e09be8e451cd3c364076623c" } } From f89fd5098bf1b14e8bbe8fcbaafb04e827a72c47 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Mon, 13 May 2024 19:47:52 +0200 Subject: [PATCH 25/34] SOmething --- tests/tests/regenesis.rs | 112 +++++++++++++-------------------------- 1 file changed, 37 insertions(+), 75 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 3f81c0834d5..266e6227af3 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -442,7 +442,8 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { core.client.submit_and_await_commit(&tx).await.unwrap(); - let block_height = core.client.produce_blocks(1, None).await.unwrap(); + let message_block_height = core.client.produce_blocks(1, None).await.unwrap(); + core.client.produce_blocks(1, None).await.unwrap(); // When let db_dir = core.kill().await; @@ -465,6 +466,15 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { snapshot_dir.path().to_str().unwrap(), ]) .await?; + core.client.produce_blocks(1, None).await.unwrap(); + let latest_block = core + .client + .chain_info() + .await + .unwrap() + .latest_block + .header + .height; let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); let message_ids: Vec<_> = receipts.iter().filter_map(|r| r.message_id()).collect(); @@ -473,81 +483,33 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { // Then assert_eq!(nonces.len(), 1); - for nonce in nonces { - let result = core - .client - .message_proof(&tx_id, nonce, None, Some(block_height)) - .await - .unwrap(); - assert!(result.is_some()); - let result = result.unwrap(); - - // 1. Generate the message id (message fields) - // Produce message id. - let generated_message_id = compute_message_id( - &result.sender, - &result.recipient, - &result.nonce, - result.amount, - &result.data, - ); - - // 2. Generate the block id. (full header) - let mut hasher = Hasher::default(); - hasher.input(result.message_block_header.prev_root.as_ref()); - hasher.input(&result.message_block_header.height.to_be_bytes()[..]); - hasher.input(result.message_block_header.time.0.to_be_bytes()); - hasher.input(result.message_block_header.application_hash.as_ref()); - let message_block_id = hasher.digest(); - assert_eq!(message_block_id, result.message_block_header.id); - - // 3. Verify the message proof. (message receipt root, message id, proof index, proof set, num message receipts in the block) - let message_proof_index = result.message_proof.proof_index; - let message_proof_set: Vec<_> = result - .message_proof - .proof_set - .iter() - .map(|bytes| *bytes.deref()) - .collect(); - assert!(binary::verify( - &result.message_block_header.message_outbox_root, - &generated_message_id, - &message_proof_set, - message_proof_index, - result.message_block_header.message_receipt_count as u64, - )); - - // Generate a proof to compare - let mut tree = binary::in_memory::MerkleTree::new(); - for id in &message_ids { - tree.push(id.as_ref()); + for block_height in message_block_height + 1..latest_block { + for nonce in nonces { + let result = core + .client + .message_proof(&tx_id, nonce, None, Some(block_height)) + .await + .unwrap(); + assert!(result.is_some()); + let result = result.unwrap(); + + // 4. Verify the block proof. (prev_root, block id, proof index, proof set, block count) + let block_proof_index = result.block_proof.proof_index; + let block_proof_set: Vec<_> = result + .block_proof + .proof_set + .iter() + .map(|bytes| *bytes.deref()) + .collect(); + let blocks_count = result.commit_block_header.height; + assert!(binary::verify( + &result.commit_block_header.prev_root, + &message_block_id, + &block_proof_set, + block_proof_index, + blocks_count as u64, + )); } - let (expected_root, expected_set) = tree.prove(message_proof_index).unwrap(); - - assert_eq!(message_proof_set, expected_set); - - // Check the root matches the proof and the root on the header. - assert_eq!( - <[u8; 32]>::from(result.message_block_header.message_outbox_root), - expected_root - ); - - // 4. Verify the block proof. (prev_root, block id, proof index, proof set, block count) - let block_proof_index = result.block_proof.proof_index; - let block_proof_set: Vec<_> = result - .block_proof - .proof_set - .iter() - .map(|bytes| *bytes.deref()) - .collect(); - let blocks_count = result.commit_block_header.height; - assert!(binary::verify( - &result.commit_block_header.prev_root, - &message_block_id, - &block_proof_set, - block_proof_index, - blocks_count as u64, - )); } Ok(()) From 6174eef61e1c11dde07bc4d64bb6a72dfbacf2e1 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Mon, 13 May 2024 20:21:38 -0400 Subject: [PATCH 26/34] Update test --- tests/tests/regenesis.rs | 81 +++++++++++++++------------------------- 1 file changed, 31 insertions(+), 50 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 266e6227af3..9bbb23c7dad 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -27,15 +27,9 @@ use fuel_core_types::{ GTFArgs, RegId, }, - fuel_crypto::{ - Hasher, - PublicKey, - }, + fuel_crypto::PublicKey, fuel_merkle::binary, - fuel_tx::{ - input::message::compute_message_id, - *, - }, + fuel_tx::*, fuel_vm::*, }; use itertools::Itertools; @@ -441,10 +435,11 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { let tx_id = tx.id(&Default::default()); core.client.submit_and_await_commit(&tx).await.unwrap(); - - let message_block_height = core.client.produce_blocks(1, None).await.unwrap(); core.client.produce_blocks(1, None).await.unwrap(); + let message_block = core.client.chain_info().await.unwrap().latest_block; + let message_block_id = message_block.header.id; + // When let db_dir = core.kill().await; @@ -466,50 +461,36 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { snapshot_dir.path().to_str().unwrap(), ]) .await?; - core.client.produce_blocks(1, None).await.unwrap(); - let latest_block = core - .client - .chain_info() - .await - .unwrap() - .latest_block - .header - .height; + core.client.produce_blocks(1, None).await.unwrap(); + let latest_block = core.client.chain_info().await.unwrap().latest_block; let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); - let message_ids: Vec<_> = receipts.iter().filter_map(|r| r.message_id()).collect(); let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); + let nonce = nonces[0]; - // Then - assert_eq!(nonces.len(), 1); - - for block_height in message_block_height + 1..latest_block { - for nonce in nonces { - let result = core - .client - .message_proof(&tx_id, nonce, None, Some(block_height)) - .await - .unwrap(); - assert!(result.is_some()); - let result = result.unwrap(); - - // 4. Verify the block proof. (prev_root, block id, proof index, proof set, block count) - let block_proof_index = result.block_proof.proof_index; - let block_proof_set: Vec<_> = result - .block_proof - .proof_set - .iter() - .map(|bytes| *bytes.deref()) - .collect(); - let blocks_count = result.commit_block_header.height; - assert!(binary::verify( - &result.commit_block_header.prev_root, - &message_block_id, - &block_proof_set, - block_proof_index, - blocks_count as u64, - )); - } + for block_height in message_block.header.height + 1..latest_block.header.height { + let proof = core + .client + .message_proof(&tx_id, nonce, None, Some(block_height.into())) + .await + .expect("Unable to get message proof") + .expect("Message proof not found"); + let prev_root = proof.commit_block_header.prev_root; + let block_proof_index = proof.block_proof.proof_index; + let block_proof_set: Vec<_> = proof + .block_proof + .proof_set + .iter() + .map(|bytes| *bytes.deref()) + .collect(); + let blocks_count = proof.commit_block_header.height as u64; + assert!(binary::verify( + &prev_root, + &message_block_id, + &block_proof_set, + block_proof_index, + blocks_count, + )); } Ok(()) From 7482083134ca0b579fef6f74f09e67af2fd91cc6 Mon Sep 17 00:00:00 2001 From: Brandon Vrooman Date: Tue, 14 May 2024 15:12:19 -0400 Subject: [PATCH 27/34] Migrate FuelBlockMerkleData/Metadata to on-chain --- crates/fuel-core/src/graphql_api/database.rs | 16 +++-- crates/fuel-core/src/graphql_api/ports.rs | 10 ++- .../src/graphql_api/worker_service.rs | 59 ++++++++-------- .../fuel-core/src/service/genesis/importer.rs | 7 +- .../src/service/genesis/importer/off_chain.rs | 70 +++++++++---------- .../src/service/genesis/importer/on_chain.rs | 45 ++++++++++++ tests/tests/regenesis.rs | 52 ++++++++++++-- 7 files changed, 178 insertions(+), 81 deletions(-) diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index 9968d08bcce..5c9af486c0d 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -268,13 +268,15 @@ impl DatabaseMessageProof for ReadView { message_block_height: &BlockHeight, commit_block_height: &BlockHeight, ) -> StorageResult { - if *message_block_height >= self.genesis_height { - self.on_chain - .block_history_proof(message_block_height, commit_block_height) - } else { - self.off_chain - .block_history_proof(message_block_height, commit_block_height) - } + // if *message_block_height >= self.genesis_height { + // self.on_chain + // .block_history_proof(message_block_height, commit_block_height) + // } else { + // self.off_chain + // .block_history_proof(message_block_height, commit_block_height) + // } + self.on_chain + .block_history_proof(message_block_height, commit_block_height) } } diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index d53b608dae6..c1a10b1d527 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -325,6 +325,10 @@ pub mod worker { }; use fuel_core_services::stream::BoxStream; use fuel_core_storage::{ + tables::merkle::{ + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, Error as StorageError, Result as StorageResult, StorageMutate, @@ -357,8 +361,10 @@ pub mod worker { + StorageMutate + StorageMutate + StorageMutate - + StorageMutate - + StorageMutate + // + StorageMutate + // + StorageMutate + // + StorageMutate + // + StorageMutate + StorageMutate + StorageMutate + StorageMutate diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index cfe58d78a1d..59096da9f03 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -35,6 +35,8 @@ use fuel_core_storage::{ tables::merkle::{ DenseMerkleMetadata, DenseMetadataKey, + FuelBlockMerkleData, + FuelBlockMerkleMetadata, }, Result as StorageResult, StorageAsMut, @@ -384,35 +386,34 @@ where Ok(()) } -pub fn copy_to_old_block_merkle_data<'a, I, T>( - block_merkle_data: I, - db: &mut T, -) -> StorageResult<()> -where - I: Iterator, - T: OffChainDatabase, -{ - for (height, block) in block_merkle_data { - db.storage::() - .insert(height, block)?; - } - Ok(()) -} - -pub fn copy_to_old_block_merkle_metadata<'a, I, T>( - block_merkle_metadata: I, - db: &mut T, -) -> StorageResult<()> -where - I: Iterator, &'a DenseMerkleMetadata)>, - T: OffChainDatabase, -{ - for (height, metadata) in block_merkle_metadata { - db.storage::() - .insert(height, metadata)?; - } - Ok(()) -} +// pub fn copy_to_old_block_merkle_data<'a, I, T>( +// block_merkle_data: I, +// db: &mut T, +// ) -> StorageResult<()> +// where +// I: Iterator, +// T: OffChainDatabase, +// { +// for (height, block) in block_merkle_data { +// db.storage::().insert(height, block)?; +// } +// Ok(()) +// } +// +// pub fn copy_to_old_block_merkle_metadata<'a, I, T>( +// block_merkle_metadata: I, +// db: &mut T, +// ) -> StorageResult<()> +// where +// I: Iterator, &'a DenseMerkleMetadata)>, +// T: OffChainDatabase, +// { +// for (height, metadata) in block_merkle_metadata { +// db.storage::() +// .insert(height, metadata)?; +// } +// Ok(()) +// } pub fn copy_to_old_transactions<'a, I, T>( transactions: I, diff --git a/crates/fuel-core/src/service/genesis/importer.rs b/crates/fuel-core/src/service/genesis/importer.rs index 2829fe70f22..9a13a3ed811 100644 --- a/crates/fuel-core/src/service/genesis/importer.rs +++ b/crates/fuel-core/src/service/genesis/importer.rs @@ -123,6 +123,8 @@ impl SnapshotImporter { self.spawn_worker_on_chain::()?; self.spawn_worker_on_chain::()?; self.spawn_worker_on_chain::()?; + self.spawn_worker_on_chain::()?; + self.spawn_worker_on_chain::()?; self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; @@ -139,8 +141,9 @@ impl SnapshotImporter { self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; - self.spawn_worker_off_chain::()?; - self.spawn_worker_off_chain::()?; + // self.spawn_worker_off_chain::()?; + // self.spawn_worker_off_chain::( + // )?; self.task_manager.wait().await?; diff --git a/crates/fuel-core/src/service/genesis/importer/off_chain.rs b/crates/fuel-core/src/service/genesis/importer/off_chain.rs index f567b4dcf0b..aec2f533efe 100644 --- a/crates/fuel-core/src/service/genesis/importer/off_chain.rs +++ b/crates/fuel-core/src/service/genesis/importer/off_chain.rs @@ -212,41 +212,41 @@ impl ImportTable for Handler { } } -impl ImportTable for Handler { - type TableInSnapshot = FuelBlockMerkleData; - type TableBeingWritten = OldFuelBlockMerkleData; - type DbDesc = OffChain; - - fn process( - &mut self, - group: Vec>, - tx: &mut StorageTransaction<&mut GenesisDatabase>, - ) -> anyhow::Result<()> { - let blocks = group - .iter() - .map(|TableEntry { key, value, .. }| (key, value)); - worker_service::copy_to_old_block_merkle_data(blocks, tx)?; - Ok(()) - } -} - -impl ImportTable for Handler { - type TableInSnapshot = FuelBlockMerkleMetadata; - type TableBeingWritten = OldFuelBlockMerkleMetadata; - type DbDesc = OffChain; - - fn process( - &mut self, - group: Vec>, - tx: &mut StorageTransaction<&mut GenesisDatabase>, - ) -> anyhow::Result<()> { - let blocks = group - .iter() - .map(|TableEntry { key, value, .. }| (key, value)); - worker_service::copy_to_old_block_merkle_metadata(blocks, tx)?; - Ok(()) - } -} +// impl ImportTable for Handler { +// type TableInSnapshot = FuelBlockMerkleData; +// type TableBeingWritten = FuelBlockMerkleData; +// type DbDesc = OffChain; +// +// fn process( +// &mut self, +// group: Vec>, +// tx: &mut StorageTransaction<&mut GenesisDatabase>, +// ) -> anyhow::Result<()> { +// let blocks = group +// .iter() +// .map(|TableEntry { key, value, .. }| (key, value)); +// worker_service::copy_to_old_block_merkle_data(blocks, tx)?; +// Ok(()) +// } +// } +// +// impl ImportTable for Handler { +// type TableInSnapshot = FuelBlockMerkleMetadata; +// type TableBeingWritten = FuelBlockMerkleMetadata; +// type DbDesc = OffChain; +// +// fn process( +// &mut self, +// group: Vec>, +// tx: &mut StorageTransaction<&mut GenesisDatabase>, +// ) -> anyhow::Result<()> { +// let blocks = group +// .iter() +// .map(|TableEntry { key, value, .. }| (key, value)); +// worker_service::copy_to_old_block_merkle_metadata(blocks, tx)?; +// Ok(()) +// } +// } impl ImportTable for Handler { type TableInSnapshot = SealedBlockConsensus; diff --git a/crates/fuel-core/src/service/genesis/importer/on_chain.rs b/crates/fuel-core/src/service/genesis/importer/on_chain.rs index e75fd097995..fa3ad50e926 100644 --- a/crates/fuel-core/src/service/genesis/importer/on_chain.rs +++ b/crates/fuel-core/src/service/genesis/importer/on_chain.rs @@ -12,6 +12,10 @@ use anyhow::anyhow; use fuel_core_chain_config::TableEntry; use fuel_core_storage::{ tables::{ + merkle::{ + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, Coins, ContractsAssets, ContractsLatestUtxo, @@ -149,6 +153,47 @@ impl ImportTable for Handler { } } +impl ImportTable for Handler { + type TableInSnapshot = FuelBlockMerkleData; + type TableBeingWritten = FuelBlockMerkleData; + type DbDesc = OnChain; + + fn process( + &mut self, + group: Vec>, + tx: &mut StorageTransaction<&mut GenesisDatabase>, + ) -> anyhow::Result<()> { + let blocks = group + .iter() + .map(|TableEntry { key, value, .. }| (key, value)); + for (height, block) in blocks { + tx.storage::().insert(height, block)?; + } + Ok(()) + } +} + +impl ImportTable for Handler { + type TableInSnapshot = FuelBlockMerkleMetadata; + type TableBeingWritten = FuelBlockMerkleMetadata; + type DbDesc = OnChain; + + fn process( + &mut self, + group: Vec>, + tx: &mut StorageTransaction<&mut GenesisDatabase>, + ) -> anyhow::Result<()> { + let blocks = group + .iter() + .map(|TableEntry { key, value, .. }| (key, value)); + for (height, metadata) in blocks { + tx.storage::() + .insert(height, metadata)?; + } + Ok(()) + } +} + fn init_coin( transaction: &mut StorageTransaction<&mut GenesisDatabase>, coin: &TableEntry, diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 9bbb23c7dad..73868251304 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -1,4 +1,5 @@ use clap::Parser; +use ethers::utils::hex; use fuel_core::{ chain_config::{ ChainConfig, @@ -438,7 +439,35 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { core.client.produce_blocks(1, None).await.unwrap(); let message_block = core.client.chain_info().await.unwrap().latest_block; - let message_block_id = message_block.header.id; + let message_block_height = message_block.header.height; + // dbg!(message_block_height); + // let message_block_id = message_block.header.id; + + let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); + let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); + let nonce = nonces[0]; + + let proof = core + .client + .message_proof(&tx_id, nonce, None, Some(message_block_height.into())) + .await + .expect("Unable to get message proof") + .expect("Message proof not found"); + let prev_root = proof.commit_block_header.prev_root; + let block_proof_index = proof.block_proof.proof_index; + let block_proof_set: Vec<_> = proof + .block_proof + .proof_set + .iter() + .map(|bytes| *bytes.deref()) + .collect(); + assert!(binary::verify( + &prev_root, + &proof.message_block_header.id, + &block_proof_set, + block_proof_index, + proof.commit_block_header.height as u64, + )); // When let db_dir = core.kill().await; @@ -468,28 +497,39 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); let nonce = nonces[0]; - for block_height in message_block.header.height + 1..latest_block.header.height { + for block_height in message_block.header.height..latest_block.header.height { + // dbg!(block_height); let proof = core .client - .message_proof(&tx_id, nonce, None, Some(block_height.into())) + // .message_proof(&tx_id, nonce, None, Some(block_height.into())) + .message_proof(&tx_id, nonce, None, Some(2.into())) .await .expect("Unable to get message proof") .expect("Message proof not found"); let prev_root = proof.commit_block_header.prev_root; - let block_proof_index = proof.block_proof.proof_index; let block_proof_set: Vec<_> = proof .block_proof .proof_set .iter() .map(|bytes| *bytes.deref()) .collect(); - let blocks_count = proof.commit_block_header.height as u64; + let block_proof_index = proof.block_proof.proof_index; + let message_block_id = proof.message_block_header.id; + // let count = proof.commit_block_header.height as u64; + let count = 2; + // dbg!( + // hex::encode(prev_root), + // message_block_id, + // &block_proof_set, + // block_proof_index, + // count + // ); assert!(binary::verify( &prev_root, &message_block_id, &block_proof_set, block_proof_index, - blocks_count, + count, )); } From d66600f84a96fc8246209b4c510d96c3d214a82c Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 11:44:24 +0200 Subject: [PATCH 28/34] Fixed regenesis --- crates/chain-config/src/config/state.rs | 18 ++--- crates/fuel-core/src/combined_database.rs | 10 ++- crates/fuel-core/src/database/block.rs | 53 +++++++++++- crates/fuel-core/src/graphql_api/database.rs | 7 -- crates/fuel-core/src/graphql_api/ports.rs | 76 +---------------- crates/fuel-core/src/graphql_api/storage.rs | 4 - .../fuel-core/src/graphql_api/storage/old.rs | 81 ------------------- .../src/graphql_api/worker_service.rs | 40 --------- .../src/service/adapters/graphql_api.rs | 22 ++++- .../service/adapters/graphql_api/off_chain.rs | 43 +--------- .../service/adapters/graphql_api/on_chain.rs | 40 --------- crates/fuel-core/src/service/genesis.rs | 2 +- .../fuel-core/src/service/genesis/exporter.rs | 14 ++-- .../fuel-core/src/service/genesis/importer.rs | 11 +-- .../src/service/genesis/importer/off_chain.rs | 48 +---------- tests/tests/regenesis.rs | 15 +--- tests/tests/snapshot.rs | 6 +- 17 files changed, 104 insertions(+), 386 deletions(-) diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index f6962746be2..2e08b096826 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -95,18 +95,12 @@ pub struct LastBlockConfig { pub consensus_parameters_version: ConsensusParametersVersion, /// The version of state transition function used to produce last block. pub state_transition_version: StateTransitionBytecodeVersion, - /// The block id of the last block - pub block_hash: Bytes32, + /// The Merkle root of all blocks before regenesis. + pub blocks_root: Bytes32, } -impl From for LastBlockConfig { - fn from(header: BlockHeader) -> Self { - Self::from(&header) - } -} - -impl From<&BlockHeader> for LastBlockConfig { - fn from(header: &BlockHeader) -> Self { +impl LastBlockConfig { + pub fn from_header(header: &BlockHeader, blocks_root: Bytes32) -> Self { Self { block_height: *header.height(), da_block_height: header.application().da_height, @@ -116,7 +110,7 @@ impl From<&BlockHeader> for LastBlockConfig { state_transition_version: header .application() .state_transition_bytecode_version, - block_hash: header.consensus().prev_root, + blocks_root, } } } @@ -297,7 +291,7 @@ impl crate::Randomize for StateConfig { da_block_height: rng.gen(), consensus_parameters_version: rng.gen(), state_transition_version: rng.gen(), - block_hash: rng.gen(), + blocks_root: rng.gen(), }), } } diff --git a/crates/fuel-core/src/combined_database.rs b/crates/fuel-core/src/combined_database.rs index 3e3a18c8860..a969a00d802 100644 --- a/crates/fuel-core/src/combined_database.rs +++ b/crates/fuel-core/src/combined_database.rs @@ -11,11 +11,13 @@ use crate::{ }, service::DbType, }; +use fuel_core_chain_config::LastBlockConfig; #[cfg(feature = "test-helpers")] use fuel_core_chain_config::{ StateConfig, StateConfigBuilder, }; +use fuel_core_producer::ports::BlockProducerDatabase; #[cfg(feature = "test-helpers")] use fuel_core_storage::tables::{ Coins, @@ -180,7 +182,13 @@ impl CombinedDatabase { ); let latest_block = self.on_chain().latest_block()?; - let state_config = builder.build(Some(latest_block.header().into()))?; + let blocks_root = self + .on_chain() + .block_header_merkle_root(latest_block.header().height())?; + let state_config = builder.build(Some(LastBlockConfig::from_header( + latest_block.header(), + blocks_root, + )))?; Ok(state_config) } diff --git a/crates/fuel-core/src/database/block.rs b/crates/fuel-core/src/database/block.rs index 3c4fe5a6450..e24bade2040 100644 --- a/crates/fuel-core/src/database/block.rs +++ b/crates/fuel-core/src/database/block.rs @@ -3,7 +3,7 @@ use crate::{ database_description::off_chain::OffChain, Database, }, - graphql_api::storage::blocks::FuelBlockIdsToHeights, + fuel_core_graphql_api::storage::blocks::FuelBlockIdsToHeights, }; use fuel_core_storage::{ iter::{ @@ -12,9 +12,15 @@ use fuel_core_storage::{ }, not_found, tables::{ + merkle::{ + DenseMetadataKey, + FuelBlockMerkleData, + FuelBlockMerkleMetadata, + }, FuelBlocks, Transactions, }, + Error as StorageError, Result as StorageResult, StorageAsRef, }; @@ -26,6 +32,8 @@ use fuel_core_types::{ }, primitives::BlockId, }, + entities::relayer::message::MerkleProof, + fuel_merkle::binary::MerkleTree, fuel_types::BlockHeight, }; use itertools::Itertools; @@ -80,11 +88,52 @@ impl Database { } } +impl Database { + pub fn block_history_proof( + &self, + message_block_height: &BlockHeight, + commit_block_height: &BlockHeight, + ) -> StorageResult { + if message_block_height > commit_block_height { + Err(anyhow::anyhow!( + "The `message_block_height` is higher than `commit_block_height`" + ))?; + } + + let message_merkle_metadata = self + .storage::() + .get(&DenseMetadataKey::Primary(*message_block_height))? + .ok_or(not_found!(FuelBlockMerkleMetadata))?; + + let commit_merkle_metadata = self + .storage::() + .get(&DenseMetadataKey::Primary(*commit_block_height))? + .ok_or(not_found!(FuelBlockMerkleMetadata))?; + + let storage = self; + let tree: MerkleTree = + MerkleTree::load(storage, commit_merkle_metadata.version()) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + + let proof_index = message_merkle_metadata + .version() + .checked_sub(1) + .ok_or(anyhow::anyhow!("The count of leaves - messages is zero"))?; + let (_, proof_set) = tree + .prove(proof_index) + .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; + + Ok(MerkleProof { + proof_set, + proof_index, + }) + } +} + #[allow(clippy::arithmetic_side_effects)] #[cfg(test)] mod tests { use super::*; - use crate::graphql_api::ports::DatabaseMessageProof; use fuel_core_storage::StorageMutate; use fuel_core_types::{ blockchain::{ diff --git a/crates/fuel-core/src/graphql_api/database.rs b/crates/fuel-core/src/graphql_api/database.rs index 5c9af486c0d..5ac6e9b5589 100644 --- a/crates/fuel-core/src/graphql_api/database.rs +++ b/crates/fuel-core/src/graphql_api/database.rs @@ -268,13 +268,6 @@ impl DatabaseMessageProof for ReadView { message_block_height: &BlockHeight, commit_block_height: &BlockHeight, ) -> StorageResult { - // if *message_block_height >= self.genesis_height { - // self.on_chain - // .block_history_proof(message_block_height, commit_block_height) - // } else { - // self.off_chain - // .block_history_proof(message_block_height, commit_block_height) - // } self.on_chain .block_history_proof(message_block_height, commit_block_height) } diff --git a/crates/fuel-core/src/graphql_api/ports.rs b/crates/fuel-core/src/graphql_api/ports.rs index c1a10b1d527..9cd1b4ebc6f 100644 --- a/crates/fuel-core/src/graphql_api/ports.rs +++ b/crates/fuel-core/src/graphql_api/ports.rs @@ -6,14 +6,12 @@ use fuel_core_storage::{ IterDirection, }, tables::{ - merkle::DenseMerkleMetadata, Coins, ContractsAssets, ContractsRawCode, Messages, }, Error as StorageError, - Mappable, Result as StorageResult, StorageInspect, }; @@ -34,7 +32,6 @@ use fuel_core_types::{ }, transaction::RelayedTransactionStatus, }, - fuel_merkle::binary, fuel_tx::{ Bytes32, ConsensusParameters, @@ -64,7 +61,7 @@ use fuel_core_types::{ }; use std::sync::Arc; -pub trait OffChainDatabase: Send + Sync + DatabaseMessageProof { +pub trait OffChainDatabase: Send + Sync { fn block_height(&self, block_id: &BlockId) -> StorageResult; fn tx_status(&self, tx_id: &TxId) -> StorageResult; @@ -181,27 +178,6 @@ pub trait DatabaseChain { fn da_height(&self) -> StorageResult; } -/// Trait that defines getters for Block Merkle data and metadata -pub trait DatabaseMerklizedBlocks { - type TableType: Mappable< - Key = u64, - Value = binary::Primitive, - OwnedValue = binary::Primitive, - >; - - fn block_merkle_data(&self, version: &u64) -> StorageResult; - - fn block_merkle_metadata( - &self, - height: &BlockHeight, - ) -> StorageResult; - - fn load_block_merkle_tree( - &self, - version: u64, - ) -> StorageResult>; -} - #[async_trait] pub trait TxPoolPort: Send + Sync { fn transaction(&self, id: TxId) -> Option; @@ -249,46 +225,6 @@ pub trait DatabaseMessageProof: Send + Sync { ) -> StorageResult; } -impl DatabaseMessageProof for T -where - T: Send - + Sync - + DatabaseMerklizedBlocks - + StorageInspect<::TableType, Error = StorageError>, -{ - fn block_history_proof( - &self, - message_block_height: &BlockHeight, - commit_block_height: &BlockHeight, - ) -> StorageResult { - if message_block_height > commit_block_height { - Err(anyhow::anyhow!( - "The `message_block_height` is higher than `commit_block_height`" - ))?; - } - - let message_merkle_metadata = self.block_merkle_metadata(message_block_height)?; - let commit_merkle_metadata = self.block_merkle_metadata(commit_block_height)?; - let version = commit_merkle_metadata.version(); - let tree = self - .load_block_merkle_tree(version) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - - let proof_index = message_merkle_metadata - .version() - .checked_sub(1) - .ok_or(anyhow::anyhow!("The count of leaves - messages is zero"))?; - let (_, proof_set) = tree - .prove(proof_index) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - - Ok(MerkleProof { - proof_set, - proof_index, - }) - } -} - #[async_trait::async_trait] pub trait P2pPort: Send + Sync { async fn all_peer_info(&self) -> anyhow::Result>; @@ -311,12 +247,10 @@ pub mod worker { OwnedMessageIds, SpentMessages, }, - old::OldFuelBlockMerkleMetadata, }, graphql_api::storage::{ old::{ OldFuelBlockConsensus, - OldFuelBlockMerkleData, OldFuelBlocks, OldTransactions, }, @@ -325,10 +259,6 @@ pub mod worker { }; use fuel_core_services::stream::BoxStream; use fuel_core_storage::{ - tables::merkle::{ - FuelBlockMerkleData, - FuelBlockMerkleMetadata, - }, Error as StorageError, Result as StorageResult, StorageMutate, @@ -361,10 +291,6 @@ pub mod worker { + StorageMutate + StorageMutate + StorageMutate - // + StorageMutate - // + StorageMutate - // + StorageMutate - // + StorageMutate + StorageMutate + StorageMutate + StorageMutate diff --git a/crates/fuel-core/src/graphql_api/storage.rs b/crates/fuel-core/src/graphql_api/storage.rs index 13c6dd972d2..d97e2363f2f 100644 --- a/crates/fuel-core/src/graphql_api/storage.rs +++ b/crates/fuel-core/src/graphql_api/storage.rs @@ -93,10 +93,6 @@ pub enum Column { /// Existence of a key in this column means that the message has been spent. /// See [`SpentMessages`](messages::SpentMessages) SpentMessages = 13, - /// See [`OldFuelBlockMerkleData`](old::OldFuelBlockMerkleData) - OldFuelBlockMerkleData = 14, - /// See [`OldFuelBlockMerkleMetadata`](old::OldFuelBlockMerkleMetadata) - OldFuelBlockMerkleMetadata = 15, } impl Column { diff --git a/crates/fuel-core/src/graphql_api/storage/old.rs b/crates/fuel-core/src/graphql_api/storage/old.rs index 3e5aff82150..a083b55c5f3 100644 --- a/crates/fuel-core/src/graphql_api/storage/old.rs +++ b/crates/fuel-core/src/graphql_api/storage/old.rs @@ -13,10 +13,6 @@ use fuel_core_storage::{ raw::Raw, }, structured_storage::TableWithBlueprint, - tables::merkle::{ - DenseMerkleMetadata, - DenseMetadataKey, - }, Mappable, }; use fuel_core_txpool::types::TxId; @@ -25,7 +21,6 @@ use fuel_core_types::{ block::CompressedBlock, consensus::Consensus, }, - fuel_merkle::binary, fuel_tx::Transaction, fuel_types::BlockHeight, }; @@ -57,58 +52,6 @@ fuel_core_storage::basic_storage_tests!( ::Value::default() ); -/// Old block Merkle data from before regenesis. -pub struct OldFuelBlockMerkleData; - -impl Mappable for OldFuelBlockMerkleData { - type Key = u64; - type OwnedKey = Self::Key; - type Value = binary::Primitive; - type OwnedValue = Self::Value; -} - -impl TableWithBlueprint for OldFuelBlockMerkleData { - type Blueprint = Plain, Postcard>; - type Column = super::Column; - - fn column() -> Self::Column { - Self::Column::OldFuelBlockMerkleData - } -} - -#[cfg(test)] -fuel_core_storage::basic_storage_tests!( - OldFuelBlockMerkleData, - ::Key::default(), - ::Value::default() -); - -/// Old block Merkle metadata from before regenesis. -pub struct OldFuelBlockMerkleMetadata; - -impl Mappable for OldFuelBlockMerkleMetadata { - type Key = DenseMetadataKey; - type OwnedKey = Self::Key; - type Value = DenseMerkleMetadata; - type OwnedValue = Self::Value; -} - -impl TableWithBlueprint for OldFuelBlockMerkleMetadata { - type Blueprint = Plain; - type Column = super::Column; - - fn column() -> Self::Column { - Self::Column::OldFuelBlockMerkleMetadata - } -} - -#[cfg(test)] -fuel_core_storage::basic_storage_tests!( - OldFuelBlockMerkleMetadata, - ::Key::default(), - ::Value::default() -); - /// Old blocks from before regenesis. /// Has same form as [`SealedBlockConsensus`](fuel_core_storage::tables::SealedBlockConsensus). pub struct OldFuelBlockConsensus; @@ -198,27 +141,3 @@ impl AddTable for StateConfigBuilder { // Do not include these for now } } - -impl AsTable for StateConfig { - fn as_table(&self) -> Vec> { - Vec::new() // Do not include these for now - } -} - -impl AddTable for StateConfigBuilder { - fn add(&mut self, _entries: Vec>) { - // Do not include these for now - } -} - -impl AsTable for StateConfig { - fn as_table(&self) -> Vec> { - Vec::new() // Do not include these for now - } -} - -impl AddTable for StateConfigBuilder { - fn add(&mut self, _entries: Vec>) { - // Do not include these for now - } -} diff --git a/crates/fuel-core/src/graphql_api/worker_service.rs b/crates/fuel-core/src/graphql_api/worker_service.rs index 59096da9f03..ad76fda9f3b 100644 --- a/crates/fuel-core/src/graphql_api/worker_service.rs +++ b/crates/fuel-core/src/graphql_api/worker_service.rs @@ -14,10 +14,6 @@ use crate::{ OwnedMessageKey, SpentMessages, }, - old::{ - OldFuelBlockMerkleData, - OldFuelBlockMerkleMetadata, - }, }, }, graphql_api::storage::relayed_transactions::RelayedTransactionStatuses, @@ -32,12 +28,6 @@ use fuel_core_services::{ StateWatcher, }; use fuel_core_storage::{ - tables::merkle::{ - DenseMerkleMetadata, - DenseMetadataKey, - FuelBlockMerkleData, - FuelBlockMerkleMetadata, - }, Result as StorageResult, StorageAsMut, }; @@ -51,7 +41,6 @@ use fuel_core_types::{ consensus::Consensus, }, entities::relayer::transaction::RelayedTransactionStatus, - fuel_merkle::binary, fuel_tx::{ field::{ Inputs, @@ -386,35 +375,6 @@ where Ok(()) } -// pub fn copy_to_old_block_merkle_data<'a, I, T>( -// block_merkle_data: I, -// db: &mut T, -// ) -> StorageResult<()> -// where -// I: Iterator, -// T: OffChainDatabase, -// { -// for (height, block) in block_merkle_data { -// db.storage::().insert(height, block)?; -// } -// Ok(()) -// } -// -// pub fn copy_to_old_block_merkle_metadata<'a, I, T>( -// block_merkle_metadata: I, -// db: &mut T, -// ) -> StorageResult<()> -// where -// I: Iterator, &'a DenseMerkleMetadata)>, -// T: OffChainDatabase, -// { -// for (height, metadata) in block_merkle_metadata { -// db.storage::() -// .insert(height, metadata)?; -// } -// Ok(()) -// } - pub fn copy_to_old_transactions<'a, I, T>( transactions: I, db: &mut T, diff --git a/crates/fuel-core/src/service/adapters/graphql_api.rs b/crates/fuel-core/src/service/adapters/graphql_api.rs index ccaa4c9b1d6..0f20ef4fffa 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api.rs @@ -9,22 +9,28 @@ use crate::{ worker, BlockProducerPort, ConsensusProvider, + DatabaseMessageProof, GasPriceEstimate, P2pPort, TxPoolPort, }, - service::adapters::{ - P2PAdapter, - TxPoolAdapter, + service::{ + adapters::{ + P2PAdapter, + TxPoolAdapter, + }, + Database, }, }; use async_trait::async_trait; use fuel_core_services::stream::BoxStream; +use fuel_core_storage::Result as StorageResult; use fuel_core_txpool::{ service::TxStatusMessage, types::TxId, }; use fuel_core_types::{ + entities::relayer::message::MerkleProof, fuel_tx::{ Bytes32, ConsensusParameters, @@ -165,3 +171,13 @@ impl ConsensusProvider for ConsensusParametersProvider { self.shared_state.latest_consensus_parameters() } } + +impl DatabaseMessageProof for Database { + fn block_history_proof( + &self, + message_block_height: &BlockHeight, + commit_block_height: &BlockHeight, + ) -> StorageResult { + Database::block_history_proof(self, message_block_height, commit_block_height) + } +} diff --git a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs index 94095632f3f..d56cf087d5d 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs @@ -10,19 +10,14 @@ use crate::{ }, storage::{ contracts::ContractsInfo, - old::OldFuelBlockMerkleMetadata, relayed_transactions::RelayedTransactionStatuses, transactions::OwnedTransactionIndexCursor, }, }, graphql_api::{ - ports::{ - DatabaseBlocks, - DatabaseMerklizedBlocks, - }, + ports::DatabaseBlocks, storage::old::{ OldFuelBlockConsensus, - OldFuelBlockMerkleData, OldFuelBlocks, OldTransactions, }, @@ -36,10 +31,6 @@ use fuel_core_storage::{ IteratorOverTable, }, not_found, - tables::merkle::{ - DenseMerkleMetadata, - DenseMetadataKey, - }, transactional::{ IntoTransaction, StorageTransaction, @@ -59,7 +50,6 @@ use fuel_core_types::{ primitives::BlockId, }, entities::relayer::transaction::RelayedTransactionStatus, - fuel_merkle::binary, fuel_tx::{ Address, Bytes32, @@ -118,37 +108,6 @@ impl DatabaseBlocks for Database { } } -impl DatabaseMerklizedBlocks for Database { - type TableType = OldFuelBlockMerkleData; - - fn block_merkle_data(&self, version: &u64) -> StorageResult { - self.storage_as_ref::() - .get(version)? - .map(Cow::into_owned) - .ok_or(not_found!(OldFuelBlockMerkleData)) - } - - fn block_merkle_metadata( - &self, - height: &BlockHeight, - ) -> StorageResult { - self.storage_as_ref::() - .get(&DenseMetadataKey::Primary(*height))? - .map(Cow::into_owned) - .ok_or(not_found!(OldFuelBlockMerkleMetadata)) - } - - fn load_block_merkle_tree( - &self, - version: u64, - ) -> StorageResult> { - let tree: binary::MerkleTree = - binary::MerkleTree::load(self, version) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - Ok(tree) - } -} - impl OffChainDatabase for Database { fn block_height(&self, id: &BlockId) -> StorageResult { self.get_block_height(id) diff --git a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs index bf626bed64b..111fbe36247 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs @@ -7,7 +7,6 @@ use crate::{ DatabaseMessages, OnChainDatabase, }, - graphql_api::ports::DatabaseMerklizedBlocks, }; use fuel_core_importer::ports::ImporterDatabase; use fuel_core_storage::{ @@ -19,12 +18,6 @@ use fuel_core_storage::{ }, not_found, tables::{ - merkle::{ - DenseMerkleMetadata, - DenseMetadataKey, - FuelBlockMerkleData, - FuelBlockMerkleMetadata, - }, FuelBlocks, SealedBlockConsensus, Transactions, @@ -44,7 +37,6 @@ use fuel_core_types::{ primitives::DaBlockHeight, }, entities::relayer::message::Message, - fuel_merkle::binary, fuel_tx::{ AssetId, Transaction, @@ -57,7 +49,6 @@ use fuel_core_types::{ }; use itertools::Itertools; -use std::borrow::Cow; impl DatabaseBlocks for Database { fn transaction(&self, tx_id: &TxId) -> StorageResult { @@ -102,37 +93,6 @@ impl DatabaseBlocks for Database { } } -impl DatabaseMerklizedBlocks for Database { - type TableType = FuelBlockMerkleData; - - fn block_merkle_data(&self, version: &u64) -> StorageResult { - self.storage::() - .get(version)? - .map(Cow::into_owned) - .ok_or(not_found!(FuelBlockMerkleData)) - } - - fn block_merkle_metadata( - &self, - height: &BlockHeight, - ) -> StorageResult { - self.storage::() - .get(&DenseMetadataKey::Primary(*height))? - .map(Cow::into_owned) - .ok_or(not_found!(FuelBlockMerkleMetadata)) - } - - fn load_block_merkle_tree( - &self, - version: u64, - ) -> StorageResult> { - let tree: binary::MerkleTree = - binary::MerkleTree::load(self, version) - .map_err(|err| StorageError::Other(anyhow::anyhow!(err)))?; - Ok(tree) - } -} - impl DatabaseMessages for Database { fn all_messages( &self, diff --git a/crates/fuel-core/src/service/genesis.rs b/crates/fuel-core/src/service/genesis.rs index ebaf8d55021..addde681eb1 100644 --- a/crates/fuel-core/src/service/genesis.rs +++ b/crates/fuel-core/src/service/genesis.rs @@ -198,7 +198,7 @@ pub fn create_genesis_block(config: &Config) -> Block { .checked_add(1) .expect("State transition bytecode version overflow"); da_height = latest_block.da_block_height; - prev_root = latest_block.block_hash; + prev_root = latest_block.blocks_root; } else { height = 0u32.into(); #[cfg(feature = "relayer")] diff --git a/crates/fuel-core/src/service/genesis/exporter.rs b/crates/fuel-core/src/service/genesis/exporter.rs index 476038b4813..3d2b1615eff 100644 --- a/crates/fuel-core/src/service/genesis/exporter.rs +++ b/crates/fuel-core/src/service/genesis/exporter.rs @@ -13,8 +13,6 @@ use crate::{ }, graphql_api::storage::old::{ OldFuelBlockConsensus, - OldFuelBlockMerkleData, - OldFuelBlockMerkleMetadata, OldFuelBlocks, OldTransactions, }, @@ -22,12 +20,14 @@ use crate::{ use fuel_core_chain_config::{ AddTable, ChainConfig, + LastBlockConfig, SnapshotFragment, SnapshotMetadata, SnapshotWriter, StateConfigBuilder, TableEntry, }; +use fuel_core_poa::ports::Database as DatabaseTrait; use fuel_core_storage::{ blueprint::BlueprintInspect, iter::IterDirection, @@ -121,8 +121,6 @@ where OldFuelBlocks, OldFuelBlockConsensus, OldTransactions, - OldFuelBlockMerkleData, - OldFuelBlockMerkleMetadata, SpentMessages ); @@ -155,6 +153,12 @@ where async fn finalize(self) -> anyhow::Result { let writer = self.create_writer()?; let latest_block = self.db.on_chain().latest_block()?; + let blocks_root = self + .db + .on_chain() + .block_header_merkle_root(latest_block.header().height())?; + let latest_block = + LastBlockConfig::from_header(latest_block.header(), blocks_root.into()); let writer_fragment = writer.partial_close()?; self.task_manager @@ -164,7 +168,7 @@ where .try_fold(writer_fragment, |fragment, next_fragment| { fragment.merge(next_fragment) })? - .finalize(Some(latest_block.header().into()), &self.prev_chain_config) + .finalize(Some(latest_block), &self.prev_chain_config) } fn create_writer(&self) -> anyhow::Result { diff --git a/crates/fuel-core/src/service/genesis/importer.rs b/crates/fuel-core/src/service/genesis/importer.rs index 9a13a3ed811..ae90fadc971 100644 --- a/crates/fuel-core/src/service/genesis/importer.rs +++ b/crates/fuel-core/src/service/genesis/importer.rs @@ -8,13 +8,7 @@ use crate::{ off_chain::OffChain, on_chain::OnChain, }, - fuel_core_graphql_api::storage::{ - messages::SpentMessages, - old::{ - OldFuelBlockMerkleData, - OldFuelBlockMerkleMetadata, - }, - }, + fuel_core_graphql_api::storage::messages::SpentMessages, graphql_api::storage::{ blocks::FuelBlockIdsToHeights, coins::OwnedCoins, @@ -141,9 +135,6 @@ impl SnapshotImporter { self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; self.spawn_worker_off_chain::()?; - // self.spawn_worker_off_chain::()?; - // self.spawn_worker_off_chain::( - // )?; self.task_manager.wait().await?; diff --git a/crates/fuel-core/src/service/genesis/importer/off_chain.rs b/crates/fuel-core/src/service/genesis/importer/off_chain.rs index aec2f533efe..58cce0dd211 100644 --- a/crates/fuel-core/src/service/genesis/importer/off_chain.rs +++ b/crates/fuel-core/src/service/genesis/importer/off_chain.rs @@ -5,13 +5,7 @@ use crate::{ database_description::off_chain::OffChain, GenesisDatabase, }, - fuel_core_graphql_api::storage::{ - messages::SpentMessages, - old::{ - OldFuelBlockMerkleData, - OldFuelBlockMerkleMetadata, - }, - }, + fuel_core_graphql_api::storage::messages::SpentMessages, graphql_api::{ storage::{ blocks::FuelBlockIdsToHeights, @@ -34,10 +28,6 @@ use crate::{ use fuel_core_chain_config::TableEntry; use fuel_core_storage::{ tables::{ - merkle::{ - FuelBlockMerkleData, - FuelBlockMerkleMetadata, - }, Coins, FuelBlocks, Messages, @@ -212,42 +202,6 @@ impl ImportTable for Handler { } } -// impl ImportTable for Handler { -// type TableInSnapshot = FuelBlockMerkleData; -// type TableBeingWritten = FuelBlockMerkleData; -// type DbDesc = OffChain; -// -// fn process( -// &mut self, -// group: Vec>, -// tx: &mut StorageTransaction<&mut GenesisDatabase>, -// ) -> anyhow::Result<()> { -// let blocks = group -// .iter() -// .map(|TableEntry { key, value, .. }| (key, value)); -// worker_service::copy_to_old_block_merkle_data(blocks, tx)?; -// Ok(()) -// } -// } -// -// impl ImportTable for Handler { -// type TableInSnapshot = FuelBlockMerkleMetadata; -// type TableBeingWritten = FuelBlockMerkleMetadata; -// type DbDesc = OffChain; -// -// fn process( -// &mut self, -// group: Vec>, -// tx: &mut StorageTransaction<&mut GenesisDatabase>, -// ) -> anyhow::Result<()> { -// let blocks = group -// .iter() -// .map(|TableEntry { key, value, .. }| (key, value)); -// worker_service::copy_to_old_block_merkle_metadata(blocks, tx)?; -// Ok(()) -// } -// } - impl ImportTable for Handler { type TableInSnapshot = SealedBlockConsensus; type TableBeingWritten = OldFuelBlockConsensus; diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index 73868251304..e873b98dc52 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -1,5 +1,4 @@ use clap::Parser; -use ethers::utils::hex; use fuel_core::{ chain_config::{ ChainConfig, @@ -498,11 +497,9 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { let nonce = nonces[0]; for block_height in message_block.header.height..latest_block.header.height { - // dbg!(block_height); let proof = core .client - // .message_proof(&tx_id, nonce, None, Some(block_height.into())) - .message_proof(&tx_id, nonce, None, Some(2.into())) + .message_proof(&tx_id, nonce, None, Some(block_height.into())) .await .expect("Unable to get message proof") .expect("Message proof not found"); @@ -515,15 +512,7 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { .collect(); let block_proof_index = proof.block_proof.proof_index; let message_block_id = proof.message_block_header.id; - // let count = proof.commit_block_header.height as u64; - let count = 2; - // dbg!( - // hex::encode(prev_root), - // message_block_id, - // &block_proof_set, - // block_proof_index, - // count - // ); + let count = proof.commit_block_header.height as u64; assert!(binary::verify( &prev_root, &message_block_id, diff --git a/tests/tests/snapshot.rs b/tests/tests/snapshot.rs index f3b19ee1a44..8d8dadb642c 100644 --- a/tests/tests/snapshot.rs +++ b/tests/tests/snapshot.rs @@ -21,7 +21,7 @@ use rand::{ async fn loads_snapshot() { let mut rng = StdRng::seed_from_u64(1234); let db = CombinedDatabase::default(); - let block_hash = rng.gen(); + let blocks_root = rng.gen(); // setup config let starting_state = StateConfig { @@ -30,7 +30,7 @@ async fn loads_snapshot() { da_block_height: DaBlockHeight(u64::MAX), consensus_parameters_version: u32::MAX - 1, state_transition_version: u32::MAX - 1, - block_hash, + blocks_root, }), ..StateConfig::randomize(&mut rng) }; @@ -48,7 +48,7 @@ async fn loads_snapshot() { da_block_height: DaBlockHeight(u64::MAX), consensus_parameters_version: u32::MAX, state_transition_version: u32::MAX, - block_hash, + blocks_root, }); // initial state From a503f29a75fdb0570819de18103c2ec325006e76 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 11:52:43 +0200 Subject: [PATCH 29/34] Minimized number of changes --- bin/fuel-core/src/cli/snapshot.rs | 6 +- crates/chain-config/src/config/state.rs | 4 +- ...ests__json_snapshot_is_human_readable.snap | 2 +- .../src/service/adapters/graphql_api.rs | 20 +++--- .../service/adapters/graphql_api/off_chain.rs | 72 +++++-------------- .../service/adapters/graphql_api/on_chain.rs | 1 - .../fuel-core/src/service/genesis/exporter.rs | 2 +- 7 files changed, 38 insertions(+), 69 deletions(-) diff --git a/bin/fuel-core/src/cli/snapshot.rs b/bin/fuel-core/src/cli/snapshot.rs index 6179a571b31..1141b5644ef 100644 --- a/bin/fuel-core/src/cli/snapshot.rs +++ b/bin/fuel-core/src/cli/snapshot.rs @@ -199,6 +199,7 @@ mod tests { use fuel_core_chain_config::{ AddTable, AsTable, + LastBlockConfig, SnapshotMetadata, SnapshotReader, StateConfig, @@ -316,7 +317,10 @@ mod tests { builder.add(self.common.contract_balance); builder - .build(Some(self.common.block.value.header().into())) + .build(Some(LastBlockConfig::from_header( + self.common.block.value.header(), + Default::default(), + ))) .unwrap() } diff --git a/crates/chain-config/src/config/state.rs b/crates/chain-config/src/config/state.rs index 2e08b096826..550f76b5f56 100644 --- a/crates/chain-config/src/config/state.rs +++ b/crates/chain-config/src/config/state.rs @@ -783,13 +783,13 @@ mod tests { let da_block_height = 14u64.into(); let consensus_parameters_version = 321u32; let state_transition_version = 123u32; - let block_hash = Bytes32::default(); + let blocks_root = Bytes32::from([123; 32]); let block_config = LastBlockConfig { block_height, da_block_height, consensus_parameters_version, state_transition_version, - block_hash, + blocks_root, }; let writer = writer(temp_dir.path()); diff --git a/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap b/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap index 263ea01a72b..32cbfcc5653 100644 --- a/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap +++ b/crates/chain-config/src/config/state/snapshots/fuel_core_chain_config__config__state__writer__tests__json_snapshot_is_human_readable.snap @@ -88,6 +88,6 @@ expression: encoded_json "da_block_height": 14074420184374977699, "consensus_parameters_version": 2019076799, "state_transition_version": 1670454246, - "block_hash": "dfa3ac8a57ea08860870fd515cf7ca6afb887dd1e09be8e451cd3c364076623c" + "blocks_root": "dfa3ac8a57ea08860870fd515cf7ca6afb887dd1e09be8e451cd3c364076623c" } } diff --git a/crates/fuel-core/src/service/adapters/graphql_api.rs b/crates/fuel-core/src/service/adapters/graphql_api.rs index 0f20ef4fffa..7ddea58c72f 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api.rs @@ -90,6 +90,16 @@ impl TxPoolPort for TxPoolAdapter { } } +impl DatabaseMessageProof for Database { + fn block_history_proof( + &self, + message_block_height: &BlockHeight, + commit_block_height: &BlockHeight, + ) -> StorageResult { + Database::block_history_proof(self, message_block_height, commit_block_height) + } +} + #[async_trait] impl BlockProducerPort for BlockProducerAdapter { async fn dry_run_txs( @@ -171,13 +181,3 @@ impl ConsensusProvider for ConsensusParametersProvider { self.shared_state.latest_consensus_parameters() } } - -impl DatabaseMessageProof for Database { - fn block_history_proof( - &self, - message_block_height: &BlockHeight, - commit_block_height: &BlockHeight, - ) -> StorageResult { - Database::block_history_proof(self, message_block_height, commit_block_height) - } -} diff --git a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs index d56cf087d5d..0b21a5d2043 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/off_chain.rs @@ -14,13 +14,10 @@ use crate::{ transactions::OwnedTransactionIndexCursor, }, }, - graphql_api::{ - ports::DatabaseBlocks, - storage::old::{ - OldFuelBlockConsensus, - OldFuelBlocks, - OldTransactions, - }, + graphql_api::storage::old::{ + OldFuelBlockConsensus, + OldFuelBlocks, + OldTransactions, }, }; use fuel_core_storage::{ @@ -65,49 +62,6 @@ use fuel_core_types::{ services::txpool::TransactionStatus, }; -use std::borrow::Cow; - -impl DatabaseBlocks for Database { - fn transaction(&self, tx_id: &TxId) -> StorageResult { - self.storage_as_ref::() - .get(tx_id)? - .map(Cow::into_owned) - .ok_or(not_found!(OldTransactions)) - } - - fn block(&self, height: &BlockHeight) -> StorageResult { - self.storage_as_ref::() - .get(height)? - .map(Cow::into_owned) - .ok_or(not_found!(OldFuelBlocks)) - } - - fn blocks( - &self, - height: Option, - direction: IterDirection, - ) -> BoxedIter<'_, StorageResult> { - self.iter_all_by_start::(height.as_ref(), Some(direction)) - .map(|r| r.map(|(_, block)| block)) - .into_boxed() - } - - fn latest_height(&self) -> StorageResult { - self.iter_all::(Some(IterDirection::Reverse)) - .next() - .transpose()? - .map(|(height, _)| height) - .ok_or(not_found!("BlockHeight")) - } - - fn consensus(&self, height: &BlockHeight) -> StorageResult { - self.storage_as_ref::() - .get(height)? - .map(Cow::into_owned) - .ok_or(not_found!(OldFuelBlockConsensus)) - } -} - impl OffChainDatabase for Database { fn block_height(&self, id: &BlockId) -> StorageResult { self.get_block_height(id) @@ -168,7 +122,13 @@ impl OffChainDatabase for Database { } fn old_block(&self, height: &BlockHeight) -> StorageResult { - ::block(self, height) + let block = self + .storage_as_ref::() + .get(height)? + .ok_or(not_found!(OldFuelBlocks))? + .into_owned(); + + Ok(block) } fn old_blocks( @@ -176,11 +136,17 @@ impl OffChainDatabase for Database { height: Option, direction: IterDirection, ) -> BoxedIter<'_, StorageResult> { - ::blocks(self, height, direction) + self.iter_all_by_start::(height.as_ref(), Some(direction)) + .map(|r| r.map(|(_, block)| block)) + .into_boxed() } fn old_block_consensus(&self, height: &BlockHeight) -> StorageResult { - ::consensus(self, height) + Ok(self + .storage_as_ref::() + .get(height)? + .ok_or(not_found!(OldFuelBlockConsensus))? + .into_owned()) } fn old_transaction(&self, id: &TxId) -> StorageResult> { diff --git a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs index 111fbe36247..7f845ce7731 100644 --- a/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs +++ b/crates/fuel-core/src/service/adapters/graphql_api/on_chain.rs @@ -47,7 +47,6 @@ use fuel_core_types::{ }, services::graphql_api::ContractBalance, }; - use itertools::Itertools; impl DatabaseBlocks for Database { diff --git a/crates/fuel-core/src/service/genesis/exporter.rs b/crates/fuel-core/src/service/genesis/exporter.rs index 3d2b1615eff..21c1f2e6e8f 100644 --- a/crates/fuel-core/src/service/genesis/exporter.rs +++ b/crates/fuel-core/src/service/genesis/exporter.rs @@ -158,7 +158,7 @@ where .on_chain() .block_header_merkle_root(latest_block.header().height())?; let latest_block = - LastBlockConfig::from_header(latest_block.header(), blocks_root.into()); + LastBlockConfig::from_header(latest_block.header(), blocks_root); let writer_fragment = writer.partial_close()?; self.task_manager From dd793795ba061b993b0b8aecb99e303d9a699e7a Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 11:59:43 +0200 Subject: [PATCH 30/34] More blocks between regenesis --- tests/tests/regenesis.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/tests/regenesis.rs b/tests/tests/regenesis.rs index e873b98dc52..0059b4bd4ac 100644 --- a/tests/tests/regenesis.rs +++ b/tests/tests/regenesis.rs @@ -435,12 +435,10 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { let tx_id = tx.id(&Default::default()); core.client.submit_and_await_commit(&tx).await.unwrap(); - core.client.produce_blocks(1, None).await.unwrap(); - let message_block = core.client.chain_info().await.unwrap().latest_block; let message_block_height = message_block.header.height; - // dbg!(message_block_height); - // let message_block_id = message_block.header.id; + + core.client.produce_blocks(10, None).await.unwrap(); let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); @@ -448,7 +446,7 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { let proof = core .client - .message_proof(&tx_id, nonce, None, Some(message_block_height.into())) + .message_proof(&tx_id, nonce, None, Some((message_block_height + 1).into())) .await .expect("Unable to get message proof") .expect("Message proof not found"); @@ -490,13 +488,13 @@ async fn test_regenesis_message_proofs_are_preserved() -> anyhow::Result<()> { ]) .await?; - core.client.produce_blocks(1, None).await.unwrap(); + core.client.produce_blocks(10, None).await.unwrap(); let latest_block = core.client.chain_info().await.unwrap().latest_block; let receipts = core.client.receipts(&tx_id).await.unwrap().unwrap(); let nonces: Vec<_> = receipts.iter().filter_map(|r| r.nonce()).collect(); let nonce = nonces[0]; - for block_height in message_block.header.height..latest_block.header.height { + for block_height in message_block_height + 1..latest_block.header.height { let proof = core .client .message_proof(&tx_id, nonce, None, Some(block_height.into())) From 2dffd3116a8d1dc8d5b5303c67a0929273f35a61 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 12:05:03 +0200 Subject: [PATCH 31/34] Make compilation happy --- crates/fuel-core/src/combined_database.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/fuel-core/src/combined_database.rs b/crates/fuel-core/src/combined_database.rs index a969a00d802..889652587b8 100644 --- a/crates/fuel-core/src/combined_database.rs +++ b/crates/fuel-core/src/combined_database.rs @@ -11,13 +11,11 @@ use crate::{ }, service::DbType, }; -use fuel_core_chain_config::LastBlockConfig; #[cfg(feature = "test-helpers")] use fuel_core_chain_config::{ StateConfig, StateConfigBuilder, }; -use fuel_core_producer::ports::BlockProducerDatabase; #[cfg(feature = "test-helpers")] use fuel_core_storage::tables::{ Coins, @@ -157,6 +155,7 @@ impl CombinedDatabase { #[cfg(feature = "test-helpers")] pub fn read_state_config(&self) -> StorageResult { use fuel_core_chain_config::AddTable; + use fuel_core_producer::ports::BlockProducerDatabase; use itertools::Itertools; let mut builder = StateConfigBuilder::default(); @@ -185,10 +184,11 @@ impl CombinedDatabase { let blocks_root = self .on_chain() .block_header_merkle_root(latest_block.header().height())?; - let state_config = builder.build(Some(LastBlockConfig::from_header( - latest_block.header(), - blocks_root, - )))?; + let state_config = + builder.build(Some(fuel_core_chain_config::LastBlockConfig::from_header( + latest_block.header(), + blocks_root, + )))?; Ok(state_config) } From 8b8eecee5bdf5fabf4a98ee592935a44259c4f1b Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 12:20:21 +0200 Subject: [PATCH 32/34] Fixed test --- crates/fuel-core/src/service/genesis.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/fuel-core/src/service/genesis.rs b/crates/fuel-core/src/service/genesis.rs index addde681eb1..24fe06425fe 100644 --- a/crates/fuel-core/src/service/genesis.rs +++ b/crates/fuel-core/src/service/genesis.rs @@ -264,6 +264,7 @@ mod tests { Randomize, StateConfig, }; + use fuel_core_producer::ports::BlockProducerDatabase; use fuel_core_services::RunnableService; use fuel_core_storage::{ tables::{ @@ -643,7 +644,13 @@ mod tests { let actual_state = db.read_state_config().unwrap(); let mut expected_state = initial_state; - expected_state.last_block = Some(Default::default()); + let mut last_block = LastBlockConfig::default(); + last_block.block_height = db.on_chain().latest_height().unwrap().unwrap(); + last_block.blocks_root = db + .on_chain() + .block_header_merkle_root(&last_block.block_height) + .unwrap(); + expected_state.last_block = Some(last_block); assert_eq!(expected_state, actual_state); } } From bc25f4dadd44e0d079c1c96426591b5aa4653a4b Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 12:30:35 +0200 Subject: [PATCH 33/34] Fixed test --- bin/fuel-core/src/cli/snapshot.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/bin/fuel-core/src/cli/snapshot.rs b/bin/fuel-core/src/cli/snapshot.rs index 1141b5644ef..a3422233e68 100644 --- a/bin/fuel-core/src/cli/snapshot.rs +++ b/bin/fuel-core/src/cli/snapshot.rs @@ -191,10 +191,13 @@ mod tests { use std::iter::repeat_with; - use fuel_core::fuel_core_graphql_api::storage::transactions::{ - OwnedTransactionIndexKey, - OwnedTransactions, - TransactionStatuses, + use fuel_core::{ + fuel_core_graphql_api::storage::transactions::{ + OwnedTransactionIndexKey, + OwnedTransactions, + TransactionStatuses, + }, + producer::ports::BlockProducerDatabase, }; use fuel_core_chain_config::{ AddTable, @@ -765,6 +768,12 @@ mod tests { .unwrap() .clone(); let contract_id = randomly_chosen_contract.contract_id; + let mut latest_block = original_state.last_block.unwrap(); + latest_block.blocks_root = db + .db + .on_chain() + .block_header_merkle_root(&latest_block.block_height) + .unwrap(); db.flush(); // when @@ -786,7 +795,7 @@ mod tests { coins: vec![], messages: vec![], contracts: vec![randomly_chosen_contract], - last_block: original_state.last_block, + last_block: Some(latest_block), } ); From 0bef67246ac49f088280f685b10d4b78b062c4f8 Mon Sep 17 00:00:00 2001 From: xgreenx Date: Wed, 15 May 2024 12:47:02 +0200 Subject: [PATCH 34/34] Fixed test --- tests/tests/snapshot.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/tests/snapshot.rs b/tests/tests/snapshot.rs index 8d8dadb642c..18821c4802b 100644 --- a/tests/tests/snapshot.rs +++ b/tests/tests/snapshot.rs @@ -10,6 +10,7 @@ use fuel_core::{ FuelService, }, }; +use fuel_core_poa::ports::Database; use fuel_core_types::blockchain::primitives::DaBlockHeight; use rand::{ rngs::StdRng, @@ -48,7 +49,10 @@ async fn loads_snapshot() { da_block_height: DaBlockHeight(u64::MAX), consensus_parameters_version: u32::MAX, state_transition_version: u32::MAX, - blocks_root, + blocks_root: db + .on_chain() + .block_header_merkle_root(&u32::MAX.into()) + .unwrap(), }); // initial state