Skip to content

Commit

Permalink
Disable SMT for ContractsAssets and ContractsState (#2048)
Browse files Browse the repository at this point in the history
Fixes #2042

Added "smt" feature to the `fuel-core-storage` to enable old behavior.
The SMT still is used in the tests and in benchmarks but disabled for
the "production" mode.

## Checklist
- [x] Breaking changes are clearly marked as such in the PR description
and changelog
- [x] New behavior is reflected in tests

### Before requesting review
- [x] I have reviewed the code myself

---------

Co-authored-by: Voxelot <[email protected]>
Co-authored-by: Mitch Turner <[email protected]>
  • Loading branch information
3 people authored Aug 2, 2024
1 parent c2f5a3a commit 982270f
Show file tree
Hide file tree
Showing 14 changed files with 565 additions and 390 deletions.
7 changes: 2 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- [1983](https://github.com/FuelLabs/fuel-core/pull/1983): Add adapters for gas price service for accessing database values

### Breaking
#### Breaking
- [2048](https://github.com/FuelLabs/fuel-core/pull/2048): Disable SMT for `ContractsAssets` and `ContractsState` for the production mode of the `fuel-core`. The SMT still is used in benchmarks and tests.
- [#1988](https://github.com/FuelLabs/fuel-core/pull/1988): Updated `fuel-vm` to `0.56.0` ([release notes](https://github.com/FuelLabs/fuel-vm/releases/tag/v0.55.0)). Adds Blob transaction support.
- [2025](https://github.com/FuelLabs/fuel-core/pull/2025): Add new V0 algorithm for gas price to services.
This change includes new flags for the CLI:
Expand All @@ -18,10 +19,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- "gas-price-threshold-percent" - the threshold percent for determining if the gas price will be increase or decreased
And the following CLI flags are serving a new purpose
- "min-gas-price" - the minimum gas price that the gas price algorithm will return

### Fixed

#### Breaking
- [2045](https://github.com/FuelLabs/fuel-core/pull/2045): Include withdrawal message only if transaction is executed successfully.
- [2041](https://github.com/FuelLabs/fuel-core/pull/2041): Add code for startup of the gas price algorithm updater so
the gas price db on startup is always in sync with the on chain db
Expand Down
1 change: 1 addition & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ ctrlc = "3.2.3"
ed25519-dalek = { version = "2.0", features = ["rand_core"] }
ethnum = "1.3"
fuel-core = { path = "../crates/fuel-core", default-features = false, features = [
"smt",
"rocksdb-production",
] }
fuel-core-chain-config = { workspace = true }
Expand Down
Binary file not shown.
7 changes: 6 additions & 1 deletion crates/fuel-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ uuid = { version = "1.1", features = ["v4"] }

[dev-dependencies]
assert_matches = "1.5"
fuel-core = { path = ".", features = ["test-helpers"] }
fuel-core = { path = ".", features = ["smt", "test-helpers"] }
fuel-core-executor = { workspace = true, features = ["std", "test-helpers"] }
fuel-core-services = { path = "./../services", features = ["test-helpers"] }
fuel-core-storage = { path = "./../storage", features = ["test-helpers"] }
Expand All @@ -82,6 +82,11 @@ test-strategy = { workspace = true }

[features]
default = ["rocksdb"]
smt = [
"fuel-core-storage/smt",
"fuel-core-executor/smt",
"fuel-core-upgradable-executor/smt",
]
p2p = ["dep:fuel-core-p2p", "dep:fuel-core-sync"]
relayer = ["dep:fuel-core-relayer"]
rocksdb = ["dep:rocksdb", "dep:tempfile", "dep:num_cpus"]
Expand Down
1 change: 1 addition & 0 deletions crates/services/executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ fuel-core-types = { workspace = true, features = ["test-helpers"] }
[features]
default = ["std"]
std = ["fuel-core-types/default"]
smt = ["fuel-core-storage/smt"]
test-helpers = [
"fuel-core-types/test-helpers",
"fuel-core-storage/test-helpers",
Expand Down
6 changes: 2 additions & 4 deletions crates/services/executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
use fuel_core_storage::{
column::Column,
kv_store::KeyValueInspect,
structured_storage::StructuredStorage,
tables::{
Coins,
ConsensusParametersVersions,
Expand Down Expand Up @@ -1769,8 +1768,7 @@ where
ref contract_id,
..
}) => {
let contract =
ContractRef::new(StructuredStorage::new(db), *contract_id);
let contract = ContractRef::new(db, *contract_id);
let utxo_info =
contract.validated_utxo(self.options.extra_tx_checks)?;
*utxo_id = *utxo_info.utxo_id();
Expand Down Expand Up @@ -1814,7 +1812,7 @@ where
})
};

let contract = ContractRef::new(StructuredStorage::new(db), *contract_id);
let contract = ContractRef::new(db, *contract_id);
contract_output.balance_root = contract.balance_root()?;
contract_output.state_root = contract.state_root()?;
}
Expand Down
138 changes: 91 additions & 47 deletions crates/services/executor/src/refs/contract.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
use core::fmt;
use fuel_core_storage::{
not_found,
tables::{
ContractsAssets,
ContractsLatestUtxo,
ContractsState,
},
tables::ContractsLatestUtxo,
Error as StorageError,
Mappable,
MerkleRoot,
MerkleRootStorage,
StorageAsRef,
StorageInspect,
};
Expand All @@ -26,6 +21,12 @@ use fuel_core_types::{
};
use std::borrow::Cow;

#[cfg(feature = "smt")]
pub use smt::*;

#[cfg(not(feature = "smt"))]
pub use not_smt::*;

/// The wrapper around `contract_id` to simplify work with `Contract` in the database.
pub struct ContractRef<Database> {
database: Database,
Expand Down Expand Up @@ -87,49 +88,98 @@ where
}
}

impl<Database> ContractRef<Database>
where
Database: MerkleRootStorage<ContractId, ContractsAssets>,
{
pub fn balance_root(
&self,
) -> Result<Bytes32, <Database as StorageInspect<ContractsAssets>>::Error> {
self.database.root(&self.contract_id).map(Into::into)
#[cfg(feature = "smt")]
mod smt {
use super::*;
use fuel_core_storage::{
tables::{
ContractsAssets,
ContractsState,
},
MerkleRootStorage,
};

impl<Database> ContractRef<Database>
where
Database: ContractStorageTrait,
{
pub fn balance_root(
&self,
) -> Result<Bytes32, <Database as StorageInspect<ContractsAssets>>::Error>
{
<Database as MerkleRootStorage<ContractId, ContractsAssets>>::root(
&self.database,
&self.contract_id,
)
.map(Into::into)
}

pub fn state_root(
&self,
) -> Result<Bytes32, <Database as StorageInspect<ContractsState>>::Error>
{
<Database as MerkleRootStorage<ContractId, ContractsState>>::root(
&self.database,
&self.contract_id,
)
.map(Into::into)
}
}
}

impl<Database> ContractRef<Database>
where
Database: MerkleRootStorage<ContractId, ContractsState>,
{
pub fn state_root(
&self,
) -> Result<Bytes32, <Database as StorageInspect<ContractsState>>::Error> {
self.database.root(&self.contract_id).map(Into::into)
pub trait ContractStorageTrait:
StorageInspect<ContractsLatestUtxo, Error = Self::InnerError>
+ MerkleRootStorage<ContractId, ContractsState, Error = Self::InnerError>
+ MerkleRootStorage<ContractId, ContractsAssets, Error = Self::InnerError>
{
type InnerError: fmt::Debug + fmt::Display + Send + Sync + 'static;
}
}

pub trait ContractStorageTrait:
StorageInspect<ContractsLatestUtxo, Error = Self::InnerError>
+ MerkleRootStorage<ContractId, ContractsState, Error = Self::InnerError>
+ MerkleRootStorage<ContractId, ContractsAssets, Error = Self::InnerError>
{
type InnerError: fmt::Debug + fmt::Display + Send + Sync + 'static;
impl<D, E> ContractStorageTrait for D
where
D: StorageInspect<ContractsLatestUtxo, Error = E>
+ MerkleRootStorage<ContractId, ContractsState, Error = E>
+ MerkleRootStorage<ContractId, ContractsAssets, Error = E>,
E: fmt::Debug + fmt::Display + Send + Sync + 'static,
{
type InnerError = E;
}
}

impl<D> ContractStorageTrait for D
where
D: StorageInspect<ContractsLatestUtxo, Error = StorageError>
+ MerkleRootStorage<ContractId, ContractsState, Error = StorageError>
+ MerkleRootStorage<ContractId, ContractsAssets, Error = StorageError>,
{
type InnerError = StorageError;
#[cfg(not(feature = "smt"))]
mod not_smt {
use super::*;
use fuel_core_storage::Error as StorageError;

impl<Database> ContractRef<Database> {
pub fn balance_root(&self) -> Result<Bytes32, StorageError> {
Ok(Bytes32::zeroed())
}
}

impl<Database> ContractRef<Database> {
pub fn state_root(&self) -> Result<Bytes32, StorageError> {
Ok(Bytes32::zeroed())
}
}

pub trait ContractStorageTrait:
StorageInspect<ContractsLatestUtxo, Error = Self::InnerError>
{
type InnerError: fmt::Debug + fmt::Display + Send + Sync + 'static;
}

impl<D, E> ContractStorageTrait for D
where
D: StorageInspect<ContractsLatestUtxo, Error = E>,
E: fmt::Debug + fmt::Display + Send + Sync + 'static,
{
type InnerError = E;
}
}

impl<'a, Database> ContractRef<&'a Database>
where
Database: ContractStorageTrait,
anyhow::Error: From<Database::InnerError>,
&'a Database: ContractStorageTrait<InnerError = StorageError>,
{
/// Returns the state root of the whole contract.
pub fn root(&self) -> anyhow::Result<MerkleRoot> {
Expand All @@ -142,15 +192,9 @@ where
.into_owned()
.utxo_id();

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

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

let contract_hash = *Hasher::default()
// `ContractId` already is based on contract's code and salt so we don't need it.
Expand Down
5 changes: 5 additions & 0 deletions crates/services/upgradable-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ fuel-core-wasm-executor = { workspace = true, optional = true, default-features
[features]
default = ["std"]
std = ["fuel-core-executor/std", "fuel-core-storage/std", "fuel-core-types/std"]
smt = [
"fuel-core-storage/smt",
"fuel-core-executor/smt",
"fuel-core-wasm-executor?/smt",
]
wasm-executor = [
"dep:anyhow",
"dep:parking_lot",
Expand Down
3 changes: 3 additions & 0 deletions crates/services/upgradable-executor/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ fn build_wasm() {
bin_dir,
];

#[cfg(feature = "smt")]
args.extend(["--features".to_owned(), "smt".to_owned()]);

let manifest_dir =
env::var_os("CARGO_MANIFEST_DIR").expect("The manifest directory is not set");
let manifest_path = Path::new(&manifest_dir);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ proptest = { workspace = true }
[features]
default = ["std"]
std = []
smt = ["fuel-core-storage/smt", "fuel-core-executor/smt"]
1 change: 1 addition & 0 deletions crates/storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,5 @@ test-case = { workspace = true }
[features]
default = ["std"]
std = ["fuel-core-types/std"]
smt = []
test-helpers = ["dep:mockall", "dep:rand"]
Loading

0 comments on commit 982270f

Please sign in to comment.