Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Consensus version-able #1596

Merged
merged 13 commits into from
Jan 23, 2024
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,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.

Expand Down
1 change: 1 addition & 0 deletions crates/fuel-core/src/database/balances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ impl Database {
(ContractsAssetKey::new(contract_id, &asset), balance)
})
.collect_vec();
#[allow(clippy::map_identity)]
<_ as StorageBatchMutate<ContractsAssets>>::init_storage(
&mut self.data,
&mut balances.iter().map(|(key, value)| (key, value)),
Expand Down
38 changes: 19 additions & 19 deletions crates/fuel-core/src/database/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,6 @@ impl TableWithBlueprint for OwnedCoins {
}
}

#[cfg(test)]
mod test {
use super::*;

fn generate_key(rng: &mut impl rand::Rng) -> <OwnedCoins as Mappable>::Key {
let mut bytes = [0u8; 65];
rng.fill(bytes.as_mut());
bytes
}

fuel_core_storage::basic_storage_tests!(
OwnedCoins,
[0u8; 65],
<OwnedCoins as Mappable>::Value::default(),
<OwnedCoins as Mappable>::Value::default(),
generate_key
);
}

impl StorageInspect<Coins> for Database {
type Error = StorageError;

Expand Down Expand Up @@ -174,3 +155,22 @@ impl Database {
Ok(Some(configs))
}
}

#[cfg(test)]
mod test {
use super::*;

fn generate_key(rng: &mut impl rand::Rng) -> <OwnedCoins as Mappable>::Key {
let mut bytes = [0u8; 65];
rng.fill(bytes.as_mut());
bytes
}

fuel_core_storage::basic_storage_tests!(
OwnedCoins,
[0u8; 65],
<OwnedCoins as Mappable>::Value::default(),
<OwnedCoins as Mappable>::Value::default(),
generate_key
);
}
1 change: 1 addition & 0 deletions crates/fuel-core/src/database/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ContractsState>>::init_storage(
&mut self.data,
&mut slots.iter().map(|(key, value)| (key, value)),
Expand Down
41 changes: 31 additions & 10 deletions crates/fuel-core/src/schema/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::scalars::{
Tai64Timestamp,
};
use crate::{
database::Database,
fuel_core_graphql_api::{
api_service::ConsensusModule,
database::ReadView,
Expand Down Expand Up @@ -52,12 +53,14 @@ use fuel_core_types::{
fuel_types,
fuel_types::BlockHeight,
};
use thiserror::Error as ThisError;

pub struct Block(pub(crate) CompressedBlock);

pub struct Header(pub(crate) BlockHeader);

#[derive(Union)]
#[non_exhaustive]
pub enum Consensus {
Genesis(Genesis),
PoA(PoAConsensus),
Expand All @@ -83,6 +86,16 @@ pub struct PoAConsensus {
signature: Signature,
}

#[derive(ThisError, Debug)]
pub enum BlockError {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure if we really want to have a custom error here. Since on the client side, it still will be a string. Maybe anyhow::Error will be enough to not complicate things.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My issue is primarily that we don't own the async_graphql::Error and we are exposing it. On second look though, these are all non-pub functions, so I don't know that it actually matters.

In fact, I'm not sure who uses these functions at all. My IDE doesn't seem to know.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh.... It's an #[Object], that's right. I'll just put things back then. I get what's going on.

#[error("Error from `async_graphql`")]
AsyncGraphQl(async_graphql::Error),
#[error("Error from `fuel_core_storage`")]
FuelCoreStorage(fuel_core_storage::Error),
MitchTurner marked this conversation as resolved.
Show resolved Hide resolved
#[error("Found unsupported consensus variant: {0}")]
UnsupportedConsensusVariant(String),
}

#[Object]
impl Block {
async fn id(&self) -> BlockId {
Expand All @@ -94,12 +107,17 @@ impl Block {
self.0.header().clone().into()
}

async fn consensus(&self, ctx: &Context<'_>) -> async_graphql::Result<Consensus> {
let query: &ReadView = ctx.data_unchecked();
async fn consensus(&self, ctx: &Context<'_>) -> Result<Consensus, BlockError> {
let query: &Database = ctx.data_unchecked();
let height = self.0.header().height();
let consensus = query.consensus(height)?;

Ok(consensus.into())
let core_consensus = query
.consensus(height)
.map_err(BlockError::FuelCoreStorage)?;

let my_consensus = core_consensus
.try_into()
.map_err(BlockError::UnsupportedConsensusVariant)?;
Ok(my_consensus)
}

async fn transactions(
Expand Down Expand Up @@ -343,13 +361,16 @@ impl From<CoreGenesis> for Genesis {
}
}

impl From<CoreConsensus> for Consensus {
fn from(consensus: CoreConsensus) -> Self {
impl TryFrom<CoreConsensus> for Consensus {
type Error = String;

fn try_from(consensus: CoreConsensus) -> Result<Self, Self::Error> {
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)),
}
}
}
2 changes: 2 additions & 0 deletions crates/services/consensus_module/src/block_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ where
Consensus::PoA(_) => {
fuel_core_poa::verifier::verify_block_fields(&self.database, block)
}
_ => Err(anyhow::anyhow!("Unsupported consensus: {:?}", consensus)),
}
}

Expand All @@ -88,6 +89,7 @@ where
header,
consensus,
),
_ => false,
}
}

Expand Down
7 changes: 7 additions & 0 deletions crates/services/importer/src/importer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub enum Error {
NotUnique(BlockHeight),
#[from]
StorageError(StorageError),
UnsupportedConsensusVariant(String),
}

impl From<Error> for anyhow::Error {
Expand Down Expand Up @@ -260,6 +261,12 @@ where
.ok_or(Error::Overflow)?
.into()
}
_ => {
return Err(Error::UnsupportedConsensusVariant(format!(
"{:?}",
consensus
)))
}
};

if expected_next_height != actual_next_height {
Expand Down
1 change: 1 addition & 0 deletions crates/types/src/blockchain/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading