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

unify chain id generation and usage #827

Merged
merged 13 commits into from
Dec 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions fuel-block-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ description = "Fuel Block Executor"

[dependencies]
anyhow = "1.0"
fuel-chain-config = { path = "../fuel-chain-config", version = "0.15.0" }
fuel-core-interfaces = { path = "../fuel-core-interfaces", version = "0.15.0" }
tokio = { version = "1.21", features = ["full"] }
5 changes: 4 additions & 1 deletion fuel-block-executor/src/refs.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
mod contract;

pub use contract::ContractRef;
pub use contract::{
ContractRef,
ContractStorageTrait,
};
56 changes: 55 additions & 1 deletion fuel-block-executor/src/refs/contract.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
use fuel_chain_config::GenesisCommitment;
use fuel_core_interfaces::{
common::{
fuel_storage::{
Mappable,
MerkleRootStorage,
StorageAsMut,
StorageAsRef,
StorageInspect,
},
fuel_tx::{
Bytes32,
ContractId,
},
prelude::{
Hasher,
MerkleRoot,
},
},
db::{
ContractsAssets,
ContractsLatestUtxo,
ContractsState,
},
executor::Error,
not_found,
};
use std::{
borrow::Cow,
error::Error as StdError,
};
use std::borrow::Cow;

/// The wrapper around `contract_id` to simplify work with `Contract` in the database.
pub struct ContractRef<Database> {
Expand Down Expand Up @@ -102,3 +112,47 @@ where
self.database.root(&self.contract_id).map(Into::into)
}
}

pub trait ContractStorageTrait<'a>:
StorageInspect<ContractsLatestUtxo, Error = Self::InnerError>
+ MerkleRootStorage<ContractId, ContractsState<'a>, Error = Self::InnerError>
+ MerkleRootStorage<ContractId, ContractsAssets<'a>, Error = Self::InnerError>
{
type InnerError: StdError + Send + Sync + 'static;
}

impl<'a, Database> GenesisCommitment for ContractRef<&'a mut Database>
where
for<'b> Database: ContractStorageTrait<'a>,
{
fn root(&mut self) -> anyhow::Result<MerkleRoot> {
let contract_id = *self.contract_id();
let utxo = self
.database()
.storage::<ContractsLatestUtxo>()
.get(&contract_id)?
.ok_or(not_found!(ContractsLatestUtxo))?
.into_owned();

let state_root = self
.database_mut()
.storage::<ContractsState>()
.root(&contract_id)?;

let balance_root = self
.database_mut()
.storage::<ContractsAssets>()
.root(&contract_id)?;

let contract_hash = *Hasher::default()
// `ContractId` already is based on contract's code and salt so we don't need it.
.chain(contract_id.as_ref())
.chain(utxo.tx_id().as_ref())
.chain([utxo.output_index()])
.chain(state_root.as_slice())
.chain(balance_root.as_slice())
.finalize();

Ok(contract_hash)
}
}
1 change: 1 addition & 0 deletions fuel-chain-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ description = "Fuel Chain config types"

[dependencies]
anyhow = "1.0"
bincode = "1.3"
fuel-core-interfaces = { path = "../fuel-core-interfaces", version = "0.15.0", features = [
"serde",
] }
Expand Down
30 changes: 30 additions & 0 deletions fuel-chain-config/src/config/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ use fuel_core_interfaces::common::{
Address,
AssetId,
},
prelude::{
Hasher,
MerkleRoot,
},
};
use itertools::Itertools;
use rand::{
Expand All @@ -22,6 +26,8 @@ use std::{
str::FromStr,
};

use crate::GenesisCommitment;

use super::{
coin::CoinConfig,
state::StateConfig,
Expand Down Expand Up @@ -123,6 +129,30 @@ impl FromStr for ChainConfig {
}
}

impl GenesisCommitment for ChainConfig {
fn root(&mut self) -> anyhow::Result<MerkleRoot> {
// TODO: Hash settlement configuration, consensus block production
let config_hash = *Hasher::default()
.chain(self.block_gas_limit.to_be_bytes())
.chain(self.transaction_parameters.root()?)
.chain(self.chain_name.as_bytes())
.finalize();

Ok(config_hash)
}
}

impl GenesisCommitment for ConsensusParameters {
fn root(&mut self) -> anyhow::Result<MerkleRoot> {
// TODO: Define hash algorithm for `ConsensusParameters`
let params_hash = Hasher::default()
.chain(bincode::serialize(&self)?)
.finalize();

Ok(params_hash.into())
}
}

/// Block production mode and settings
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum BlockProduction {
Expand Down
43 changes: 35 additions & 8 deletions fuel-chain-config/src/config/coin.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
use crate::serialization::{
HexNumber,
HexType,
use crate::{
serialization::{
HexNumber,
HexType,
},
GenesisCommitment,
};
use fuel_core_interfaces::{
common::fuel_types::{
Address,
AssetId,
Bytes32,
common::{
fuel_types::{
Address,
AssetId,
Bytes32,
},
prelude::{
Hasher,
MerkleRoot,
},
},
model::{
BlockHeight,
Coin,
},
model::BlockHeight,
};

use serde::{
Expand Down Expand Up @@ -45,3 +57,18 @@ pub struct CoinConfig {
#[serde_as(as = "HexType")]
pub asset_id: AssetId,
}

impl GenesisCommitment for Coin {
fn root(&mut self) -> anyhow::Result<MerkleRoot> {
let coin_hash = *Hasher::default()
.chain(self.owner)
.chain(self.amount.to_be_bytes())
.chain(self.asset_id)
.chain((*self.maturity).to_be_bytes())
.chain([self.status as u8])
.chain((*self.block_created).to_be_bytes())
.finalize();

Ok(coin_hash)
}
}
16 changes: 13 additions & 3 deletions fuel-chain-config/src/config/message.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
use crate::serialization::{
HexNumber,
HexType,
use crate::{
serialization::{
HexNumber,
HexType,
},
GenesisCommitment,
};
use fuel_core_interfaces::{
common::prelude::{
Address,
MerkleRoot,
Word,
},
model::{
Expand Down Expand Up @@ -53,3 +57,9 @@ impl From<MessageConfig> for Message {
}
}
}

impl GenesisCommitment for Message {
fn root(&mut self) -> anyhow::Result<MerkleRoot> {
Ok(self.id().into())
}
}
25 changes: 25 additions & 0 deletions fuel-chain-config/src/genesis.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use fuel_core_interfaces::{
common::prelude::{
Hasher,
MerkleRoot,
},
model::Genesis,
};

pub trait GenesisCommitment {
/// Calculates the merkle root of the state of the entity.
fn root(&mut self) -> anyhow::Result<MerkleRoot>;
}

impl GenesisCommitment for Genesis {
fn root(&mut self) -> anyhow::Result<MerkleRoot> {
let genesis_hash = *Hasher::default()
.chain(self.chain_config_hash)
.chain(self.coins_root)
leviathanbeak marked this conversation as resolved.
Show resolved Hide resolved
.chain(self.contracts_root)
.chain(self.messages_root)
.finalize();

Ok(genesis_hash)
}
}
2 changes: 2 additions & 0 deletions fuel-chain-config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
pub mod config;
mod genesis;
mod serialization;

pub use config::*;
pub use genesis::GenesisCommitment;
2 changes: 1 addition & 1 deletion fuel-core-interfaces/src/model/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ impl From<FuelBlock> for PartialFuelBlock {
/// network - contracts states, contracts balances, unspent coins, and messages. It also contains
/// the hash on the initial config of the network that defines the consensus rules for following
/// blocks.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Genesis {
/// The chain config define what consensus type to use, what settlement layer to use,
Expand Down
11 changes: 2 additions & 9 deletions fuel-core/src/cli/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub struct Command {

#[cfg(feature = "p2p")]
#[clap(flatten)]
pub p2p_args: p2p::P2pArgs,
pub p2p_args: p2p::P2PArgs,

#[clap(long = "metrics")]
pub metrics: bool,
Expand Down Expand Up @@ -143,14 +143,7 @@ impl Command {
let chain_conf: ChainConfig = chain_config.as_str().parse()?;

#[cfg(feature = "p2p")]
let p2p_cfg = {
let mut p2p = match p2p_args.into_config(&chain_conf) {
Ok(value) => value,
Err(e) => return Err(e),
};
p2p.metrics = metrics;
p2p
};
let p2p_cfg = p2p_args.into_config(metrics)?;

// if consensus key is not configured, fallback to dev consensus key
let consensus_key = load_consensus_key(consensus_key)?.or_else(|| {
Expand Down
23 changes: 11 additions & 12 deletions fuel-core/src/cli/run/p2p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ use std::{

use clap::Args;

use fuel_chain_config::ChainConfig;
use fuel_core_interfaces::common::fuel_crypto;
use fuel_p2p::{
config::P2PConfig,
config::{
NotInitialized,
P2PConfig,
},
gossipsub_config::default_gossipsub_builder,
Multiaddr,
};

#[derive(Debug, Clone, Args)]
pub struct P2pArgs {
pub struct P2PArgs {
/// Path to the location of DER-encoded Secp256k1 Keypair
#[clap(long = "keypair")]
pub keypair: Option<PathBuf>,
Expand Down Expand Up @@ -132,12 +134,8 @@ pub struct P2pArgs {
pub connection_keep_alive: u64,
}

impl P2pArgs {
pub fn into_config(self, chain_config: &ChainConfig) -> anyhow::Result<P2PConfig> {
let checksum = *fuel_crypto::Hasher::default()
.chain(bincode::serialize(chain_config)?)
.finalize();

impl P2PArgs {
pub fn into_config(self, metrics: bool) -> anyhow::Result<P2PConfig<NotInitialized>> {
let local_keypair = {
match self.keypair {
Some(path) => {
Expand Down Expand Up @@ -181,9 +179,9 @@ impl P2pArgs {
};

Ok(P2PConfig {
local_keypair,
keypair: local_keypair,
network_name: self.network,
checksum,
checksum: Default::default(),
address: self
.address
.unwrap_or_else(|| IpAddr::V4(Ipv4Addr::from([0, 0, 0, 0]))),
Expand All @@ -206,7 +204,8 @@ impl P2pArgs {
set_connection_keep_alive: Duration::from_secs(self.connection_keep_alive),
info_interval: Some(Duration::from_secs(self.info_interval)),
identify_interval: Some(Duration::from_secs(self.identify_interval)),
metrics: false,
metrics,
state: NotInitialized,
})
}
}
Loading