From 5bb58746421c90c914db3b62fb8acb9c88100535 Mon Sep 17 00:00:00 2001 From: Mitchell Turner Date: Mon, 22 Jan 2024 16:17:08 -0800 Subject: [PATCH] Make `Consensus` version-able (#1596) Part of: https://github.com/FuelLabs/fuel-core/issues/1544 --------- Co-authored-by: Hannes Karppila --- CHANGELOG.md | 2 +- crates/fuel-core/src/database/balances.rs | 1 + crates/fuel-core/src/database/coin.rs | 38 +++++++++---------- crates/fuel-core/src/database/state.rs | 1 + crates/fuel-core/src/schema/block.rs | 22 +++++++---- .../consensus_module/src/block_verifier.rs | 2 + crates/services/importer/src/importer.rs | 7 ++++ crates/types/src/blockchain/consensus.rs | 1 + 8 files changed, 46 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6e7dd50480..a64d66488f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ Description of the upcoming release here. - [#1601](https://github.com/FuelLabs/fuel-core/pull/1601): Fix formatting in docs and check that `cargo doc` passes in the CI. #### Breaking - +- [#1596](https://github.com/FuelLabs/fuel-core/pull/1596) Make `Consensus` type a version-able enum - [#1593](https://github.com/FuelLabs/fuel-core/pull/1593) Make `Block` type a version-able enum - [#1576](https://github.com/FuelLabs/fuel-core/pull/1576): The change moves the implementation of the storage traits for required tables from `fuel-core` to `fuel-core-storage` crate. The change also adds a more flexible configuration of the encoding/decoding per the table and allows the implementation of specific behaviors for the table in a much easier way. It unifies the encoding between database, SMTs, and iteration, preventing mismatching bytes representation on the Rust type system level. Plus, it increases the re-usage of the code by applying the same blueprint to other tables. diff --git a/crates/fuel-core/src/database/balances.rs b/crates/fuel-core/src/database/balances.rs index 84eb0c7f7e3..c9f7783db0f 100644 --- a/crates/fuel-core/src/database/balances.rs +++ b/crates/fuel-core/src/database/balances.rs @@ -30,6 +30,7 @@ impl Database { (ContractsAssetKey::new(contract_id, &asset), balance) }) .collect_vec(); + #[allow(clippy::map_identity)] <_ as StorageBatchMutate>::init_storage( &mut self.data, &mut balances.iter().map(|(key, value)| (key, value)), diff --git a/crates/fuel-core/src/database/coin.rs b/crates/fuel-core/src/database/coin.rs index ad7dfc15602..52a1a7e4a92 100644 --- a/crates/fuel-core/src/database/coin.rs +++ b/crates/fuel-core/src/database/coin.rs @@ -60,25 +60,6 @@ impl TableWithBlueprint for OwnedCoins { } } -#[cfg(test)] -mod test { - use super::*; - - fn generate_key(rng: &mut impl rand::Rng) -> ::Key { - let mut bytes = [0u8; 65]; - rng.fill(bytes.as_mut()); - bytes - } - - fuel_core_storage::basic_storage_tests!( - OwnedCoins, - [0u8; 65], - ::Value::default(), - ::Value::default(), - generate_key - ); -} - impl StorageInspect for Database { type Error = StorageError; @@ -174,3 +155,22 @@ impl Database { Ok(Some(configs)) } } + +#[cfg(test)] +mod test { + use super::*; + + fn generate_key(rng: &mut impl rand::Rng) -> ::Key { + let mut bytes = [0u8; 65]; + rng.fill(bytes.as_mut()); + bytes + } + + fuel_core_storage::basic_storage_tests!( + OwnedCoins, + [0u8; 65], + ::Value::default(), + ::Value::default(), + generate_key + ); +} diff --git a/crates/fuel-core/src/database/state.rs b/crates/fuel-core/src/database/state.rs index 53bed4b8e8e..efa6be36b55 100644 --- a/crates/fuel-core/src/database/state.rs +++ b/crates/fuel-core/src/database/state.rs @@ -25,6 +25,7 @@ impl Database { let slots = slots .map(|(key, value)| (ContractsStateKey::new(contract_id, &key), value)) .collect_vec(); + #[allow(clippy::map_identity)] <_ as StorageBatchMutate>::init_storage( &mut self.data, &mut slots.iter().map(|(key, value)| (key, value)), diff --git a/crates/fuel-core/src/schema/block.rs b/crates/fuel-core/src/schema/block.rs index 41c3f75b92f..5c341a4c47c 100644 --- a/crates/fuel-core/src/schema/block.rs +++ b/crates/fuel-core/src/schema/block.rs @@ -3,6 +3,7 @@ use super::scalars::{ Tai64Timestamp, }; use crate::{ + database::Database, fuel_core_graphql_api::{ api_service::ConsensusModule, database::ReadView, @@ -58,6 +59,7 @@ pub struct Block(pub(crate) CompressedBlock); pub struct Header(pub(crate) BlockHeader); #[derive(Union)] +#[non_exhaustive] pub enum Consensus { Genesis(Genesis), PoA(PoAConsensus), @@ -95,11 +97,12 @@ impl Block { } async fn consensus(&self, ctx: &Context<'_>) -> async_graphql::Result { - let query: &ReadView = ctx.data_unchecked(); + let query: &Database = ctx.data_unchecked(); let height = self.0.header().height(); - let consensus = query.consensus(height)?; + let core_consensus = query.consensus(height)?; - Ok(consensus.into()) + let my_consensus = core_consensus.try_into()?; + Ok(my_consensus) } async fn transactions( @@ -343,13 +346,16 @@ impl From for Genesis { } } -impl From for Consensus { - fn from(consensus: CoreConsensus) -> Self { +impl TryFrom for Consensus { + type Error = String; + + fn try_from(consensus: CoreConsensus) -> Result { match consensus { - CoreConsensus::Genesis(genesis) => Consensus::Genesis(genesis.into()), - CoreConsensus::PoA(poa) => Consensus::PoA(PoAConsensus { + CoreConsensus::Genesis(genesis) => Ok(Consensus::Genesis(genesis.into())), + CoreConsensus::PoA(poa) => Ok(Consensus::PoA(PoAConsensus { signature: poa.signature.into(), - }), + })), + _ => Err(format!("Unknown consensus type: {:?}", consensus)), } } } diff --git a/crates/services/consensus_module/src/block_verifier.rs b/crates/services/consensus_module/src/block_verifier.rs index 1b35545b04a..7be7de4d0c3 100644 --- a/crates/services/consensus_module/src/block_verifier.rs +++ b/crates/services/consensus_module/src/block_verifier.rs @@ -72,6 +72,7 @@ where Consensus::PoA(_) => { fuel_core_poa::verifier::verify_block_fields(&self.database, block) } + _ => Err(anyhow::anyhow!("Unsupported consensus: {:?}", consensus)), } } @@ -88,6 +89,7 @@ where header, consensus, ), + _ => false, } } diff --git a/crates/services/importer/src/importer.rs b/crates/services/importer/src/importer.rs index d75709e1c9e..60cc3c1f096 100644 --- a/crates/services/importer/src/importer.rs +++ b/crates/services/importer/src/importer.rs @@ -93,6 +93,7 @@ pub enum Error { NotUnique(BlockHeight), #[from] StorageError(StorageError), + UnsupportedConsensusVariant(String), } impl From for anyhow::Error { @@ -260,6 +261,12 @@ where .ok_or(Error::Overflow)? .into() } + _ => { + return Err(Error::UnsupportedConsensusVariant(format!( + "{:?}", + consensus + ))) + } }; if expected_next_height != actual_next_height { diff --git a/crates/types/src/blockchain/consensus.rs b/crates/types/src/blockchain/consensus.rs index 65022496f54..408e0373476 100644 --- a/crates/types/src/blockchain/consensus.rs +++ b/crates/types/src/blockchain/consensus.rs @@ -16,6 +16,7 @@ use poa::PoAConsensus; #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[non_exhaustive] /// The consensus related data that doesn't live on the /// header. pub enum Consensus {