Skip to content

Commit

Permalink
Added support of customization of the state transition version in the…
Browse files Browse the repository at this point in the history
… `ChainConfig` (#1929)

Closes #1920

The change allows customizing the state transition version in the
genesis block. It is helpful if you want to start a new chain with the
latest `fuel-core`.

## Checklist
- [x] New behavior is reflected in tests

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

---------

Co-authored-by: Hannes Karppila <hannes.karppila@gmail.com>
  • Loading branch information
xgreenx and Dentosal authored Jun 3, 2024
1 parent 91b6b52 commit 0324d9c
Show file tree
Hide file tree
Showing 15 changed files with 137 additions and 70 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added
- [#1929](https://github.com/FuelLabs/fuel-core/pull/1929): Added support of customization of the state transition version in the `ChainConfig`.

### Removed
- [#1913](https://github.com/FuelLabs/fuel-core/pull/1913): Removed dead code from the project.

Expand Down
4 changes: 4 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 bin/fuel-core/chainspec/local-testnet/chain_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
"privileged_address": "b62c6f41c4c380d78ae67a8b432a4a41e2465383f8cc9869b67106835685c388"
}
},
"genesis_state_transition_version": 1,
"consensus": {
"PoA": {
"signing_key": "e8df6d432b2584a3ea9d0badf297c3b525bae71b577d22c1ccc12519adb64d92"
Expand Down
Binary file not shown.
9 changes: 8 additions & 1 deletion crates/chain-config/src/config/chain.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use fuel_core_storage::MerkleRoot;
use fuel_core_types::{
blockchain::header::StateTransitionBytecodeVersion,
fuel_crypto::Hasher,
fuel_tx::ConsensusParameters,
fuel_types::{
Expand Down Expand Up @@ -32,8 +33,11 @@ pub const BYTECODE_NAME: &str = "state_transition_bytecode.wasm";
pub struct ChainConfig {
pub chain_name: String,
pub consensus_parameters: ConsensusParameters,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
pub genesis_state_transition_version: Option<StateTransitionBytecodeVersion>,
/// Note: The state transition bytecode is stored in a separate file
/// under the `BYTECODE NAME` name in serialization form.
/// under the `BYTECODE_NAME` name in serialization form.
#[serde(skip)]
#[derivative(Debug(format_with = "fmt_truncated_hex::<16>"))]
pub state_transition_bytecode: Vec<u8>,
Expand All @@ -46,6 +50,9 @@ impl Default for ChainConfig {
Self {
chain_name: "local".into(),
consensus_parameters: ConsensusParameters::default(),
genesis_state_transition_version: Some(
fuel_core_types::blockchain::header::LATEST_STATE_TRANSITION_VERSION,
),
// Note: It is invalid bytecode.
state_transition_bytecode: vec![123; 1024],
consensus: ConsensusConfig::default_poa(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ expression: json
"privileged_address": "0000000000000000000000000000000000000000000000000000000000000000"
}
},
"genesis_state_transition_version": 1,
"consensus": {
"PoA": {
"signing_key": "22ec92c3105c942a6640bdc4e4907286ec4728e8cfc0d8ac59aad4d8e1ccaefb"
Expand Down
4 changes: 3 additions & 1 deletion crates/fuel-core/src/service/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ impl Config {
// In tests, we always want to use the native executor as a default configuration.
let native_executor_version = latest_block
.map(|last_block| last_block.state_transition_version.saturating_add(1))
.unwrap_or(StateTransitionBytecodeVersion::MIN);
.unwrap_or(
fuel_core_types::blockchain::header::LATEST_STATE_TRANSITION_VERSION,
);

let utxo_validation = false;
let min_gas_price = 0;
Expand Down
12 changes: 11 additions & 1 deletion crates/fuel-core/src/service/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,11 @@ pub fn create_genesis_block(config: &Config) -> Block {
da_height = 0u64.into();
}
consensus_parameters_version = ConsensusParametersVersion::MIN;
state_transition_bytecode_version = StateTransitionBytecodeVersion::MIN;
state_transition_bytecode_version = config
.snapshot_reader
.chain_config()
.genesis_state_transition_version
.unwrap_or(StateTransitionBytecodeVersion::MIN);
prev_root = Bytes32::zeroed();
}

Expand Down Expand Up @@ -646,6 +650,12 @@ mod tests {
let mut expected_state = initial_state;
let mut last_block = LastBlockConfig::default();
last_block.block_height = db.on_chain().latest_height().unwrap().unwrap();
last_block.state_transition_version = db
.on_chain()
.latest_block()
.unwrap()
.header()
.state_transition_bytecode_version;
last_block.blocks_root = db
.on_chain()
.block_header_merkle_root(&last_block.block_height)
Expand Down
2 changes: 1 addition & 1 deletion tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ rand = { workspace = true }
reqwest = { workspace = true }
rstest = "0.15"
serde_json = { workspace = true }
tempfile = "3.3"
tempfile = { workspace = true }
test-case = { workspace = true }
test-helpers = { path = "./test-helpers" }
tokio = { workspace = true, features = [
Expand Down
4 changes: 4 additions & 0 deletions tests/test-helpers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = { workspace = true }
clap = { workspace = true }
fuel-core = { path = "../../crates/fuel-core", default-features = false, features = [
"test-helpers",
] }
fuel-core-bin = { path = "../../bin/fuel-core", features = ["parquet", "p2p"] }
fuel-core-client = { path = "../../crates/client", features = ["test-helpers"] }
fuel-core-p2p = { path = "../../crates/services/p2p", features = [
"test-helpers",
Expand All @@ -29,3 +32,4 @@ fuel-core-txpool = { path = "../../crates/services/txpool", features = [
fuel-core-types = { path = "../../crates/types", features = ["test-helpers"] }
itertools = { workspace = true }
rand = { workspace = true }
tempfile = { workspace = true }
56 changes: 56 additions & 0 deletions tests/test-helpers/src/fuel_core_driver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use clap::Parser;
use fuel_core::service::{
FuelService,
ServiceTrait,
};
use fuel_core_client::client::FuelClient;
use tempfile::{
tempdir,
TempDir,
};

pub struct FuelCoreDriver {
/// This must be before the db_dir as the drop order matters here
pub node: FuelService,
pub db_dir: TempDir,
pub client: FuelClient,
}
impl FuelCoreDriver {
pub async fn spawn(extra_args: &[&str]) -> anyhow::Result<Self> {
// Generate temp params
let db_dir = tempdir()?;

let mut args = vec![
"_IGNORED_",
"--db-path",
db_dir.path().to_str().unwrap(),
"--port",
"0",
];
args.extend(extra_args);

let node = fuel_core_bin::cli::run::get_service(
fuel_core_bin::cli::run::Command::parse_from(args),
)?;

node.start_and_await().await?;

let client = FuelClient::from(node.shared.graph_ql.bound_address);
Ok(Self {
node,
db_dir,
client,
})
}

/// Stops the node, returning the db only
/// Ignoring the return value drops the db as well.
pub async fn kill(self) -> TempDir {
println!("Stopping fuel service");
self.node
.stop_and_await()
.await
.expect("Failed to stop the node");
self.db_dir
}
}
1 change: 1 addition & 0 deletions tests/test-helpers/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod builder;
pub mod fuel_core_driver;
2 changes: 1 addition & 1 deletion tests/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ mod coins;
mod contract;
mod dap;
mod debugger;
mod deployment;
mod fee_collection_contract;
mod local_node;

mod gas_price;
mod health;
Expand Down
43 changes: 39 additions & 4 deletions tests/tests/deployment.rs → tests/tests/local_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ use fuel_core::chain_config::{
StateConfig,
TableEncoding,
};
use fuel_core_types::fuel_tx::GasCosts;
use fuel_core_types::{
blockchain::header::LATEST_STATE_TRANSITION_VERSION,
fuel_tx::GasCosts,
};
use fuel_core_upgradable_executor::WASM_BYTECODE;
use test_helpers::fuel_core_driver::FuelCoreDriver;

#[test]
fn test_deployment_chainconfig() -> anyhow::Result<()> {
fn local_chainconfig_validity() -> anyhow::Result<()> {
let path = "./../bin/fuel-core/chainspec/local-testnet";
let stored_snapshot = SnapshotMetadata::read(path).unwrap();
let mut chain_config = ChainConfig::from_snapshot_metadata(&stored_snapshot)?;
Expand All @@ -26,8 +30,16 @@ fn test_deployment_chainconfig() -> anyhow::Result<()> {

if env::var_os("OVERRIDE_CHAIN_CONFIGS").is_some() {
chain_config.state_transition_bytecode = WASM_BYTECODE.to_vec();
chain_config.genesis_state_transition_version =
Some(LATEST_STATE_TRANSITION_VERSION);
std::fs::remove_file(&stored_snapshot.chain_config)?;
chain_config.write(&stored_snapshot.chain_config)?;
} else {
assert_eq!(
chain_config.genesis_state_transition_version,
Some(LATEST_STATE_TRANSITION_VERSION),
"Genesis state transition version should match the one in the local configuration"
);
}

let temp_dir = tempfile::tempdir()?;
Expand All @@ -42,7 +54,7 @@ fn test_deployment_chainconfig() -> anyhow::Result<()> {
.to_string();
assert_eq!(
chain_config, stored_chain_config,
"Chain config should match the one in the deployment directory"
"Chain config should match the one in the local configuration"
);

let stored_state_config = {
Expand All @@ -65,8 +77,31 @@ fn test_deployment_chainconfig() -> anyhow::Result<()> {
};
assert_eq!(
stored_state_config, generated_state_config,
"State config should match the one in the deployment directory"
"State config should match the one in the local configuration"
);

Ok(())
}

#[tokio::test]
async fn start_local_node_without_any_arguments() {
// Given
let arguments = [];

// When
let service = FuelCoreDriver::spawn(&arguments).await.unwrap();

// Then
let block = service
.client
.block_by_height(0u32.into())
.await
.unwrap()
.unwrap();

assert_eq!(block.header.height, 0u32);
assert_eq!(
block.header.state_transition_bytecode_version,
LATEST_STATE_TRANSITION_VERSION
);
}
65 changes: 4 additions & 61 deletions tests/tests/regenesis.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
use clap::Parser;
use fuel_core::{
chain_config::{
ChainConfig,
LastBlockConfig,
SnapshotWriter,
},
service::{
FuelService,
ServiceTrait,
},
use fuel_core::chain_config::{
ChainConfig,
SnapshotWriter,
};
use fuel_core_bin::cli::snapshot;
use fuel_core_client::client::{
Expand All @@ -23,7 +16,6 @@ use fuel_core_client::client::{
FuelClient,
};
use fuel_core_types::{
blockchain::header::LATEST_STATE_TRANSITION_VERSION,
fuel_asm::{
op,
GTFArgs,
Expand All @@ -45,52 +37,7 @@ use tempfile::{
tempdir,
TempDir,
};

pub struct FuelCoreDriver {
/// This must be before the db_dir as the drop order matters here
pub node: FuelService,
pub db_dir: TempDir,
pub client: FuelClient,
}
impl FuelCoreDriver {
pub async fn spawn(extra_args: &[&str]) -> anyhow::Result<Self> {
// Generate temp params
let db_dir = tempdir()?;

let mut args = vec![
"_IGNORED_",
"--db-path",
db_dir.path().to_str().unwrap(),
"--port",
"0",
];
args.extend(extra_args);

let node = fuel_core_bin::cli::run::get_service(
fuel_core_bin::cli::run::Command::parse_from(args),
)?;

node.start_and_await().await?;

let client = FuelClient::from(node.shared.graph_ql.bound_address);
Ok(Self {
node,
db_dir,
client,
})
}

/// Stops the node, returning the db only
/// Ignoring the return value drops the db as well.
pub async fn kill(self) -> TempDir {
println!("Stopping fuel service");
self.node
.stop_and_await()
.await
.expect("Failed to stop the node");
self.db_dir
}
}
use test_helpers::fuel_core_driver::FuelCoreDriver;

async fn produce_block_with_tx(rng: &mut StdRng, client: &FuelClient) {
let secret = SecretKey::random(rng);
Expand Down Expand Up @@ -254,10 +201,6 @@ async fn test_regenesis_spent_messages_are_preserved() -> anyhow::Result<()> {
data: vec![],
da_height: Default::default(),
}],
last_block: Some(LastBlockConfig {
state_transition_version: LATEST_STATE_TRANSITION_VERSION - 1,
..Default::default()
}),
..Default::default()
};
let writer = SnapshotWriter::json(state_config_dir.path());
Expand Down

0 comments on commit 0324d9c

Please sign in to comment.