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

feat(node): consistent genesis #1016

Merged
merged 40 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
19f93f5
complete flow
May 30, 2024
fcdc70f
convert fendermint to cometbft genesis
Jun 3, 2024
3d8f00f
remove deprecated fields
Jun 3, 2024
8a8efd6
fix cursor
Jun 3, 2024
3890de4
fix genesis app bytes
Jun 3, 2024
14e6dea
fmt
Jun 3, 2024
4dc0482
minor changes
Jun 4, 2024
02b183f
Fix cicd (#1023)
cryptoAtwill Jun 5, 2024
d88face
Fix cicd (#1025)
cryptoAtwill Jun 6, 2024
2a4d428
Fix cicd (#1027)
cryptoAtwill Jun 10, 2024
0e31699
Merge branch 'main' of protocol-github:consensus-shipyard/ipc into si…
Jun 10, 2024
0d1c55c
Merge branch 'simple-genesis' of protocol-github:consensus-shipyard/i…
Jun 10, 2024
d551aed
Merge branch 'main' into simple-genesis
cryptoAtwill Aug 5, 2024
22219f1
Update fendermint/vm/interpreter/src/genesis.rs
cryptoAtwill Aug 7, 2024
6a1b4dd
Update fendermint/vm/interpreter/src/genesis.rs
cryptoAtwill Aug 7, 2024
7c6276b
review feedbacks
Aug 7, 2024
c4b7e66
Merge branch 'simple-genesis' of protocol-github:consensus-shipyard/i…
Aug 7, 2024
fa0f330
add genesis app state schema
Aug 7, 2024
b0038cc
update infra and simplify genesis
Aug 8, 2024
22e5958
fmt
Aug 8, 2024
0319141
fix infra
Aug 8, 2024
7a86832
Merge branch 'main' of protocol-github:consensus-shipyard/ipc into si…
Aug 13, 2024
79d1264
merge with main
Aug 13, 2024
0ae95c8
Update fevm-contract-tests.yaml
cryptoAtwill Aug 14, 2024
fa372d6
Update fevm-contract-tests.yaml
cryptoAtwill Aug 14, 2024
5332a31
Update testnode.toml
cryptoAtwill Aug 14, 2024
ed66780
skip fendermint build
Aug 14, 2024
272c29c
remove pull
Aug 14, 2024
0db23d2
Merge branch 'main' into simple-genesis
raulk Aug 16, 2024
ef2740c
rename to genesis builder
Aug 19, 2024
4ba0219
Merge branch 'simple-genesis' of protocol-github:consensus-shipyard/i…
Aug 19, 2024
47556e9
fix(node): remove genesis interpreter (#1118)
cryptoAtwill Aug 21, 2024
37a5522
Merge branch 'main' into simple-genesis
raulk Aug 23, 2024
38fbeed
Merge branch 'main' into simple-genesis
raulk Aug 26, 2024
86d1cf9
clean up read_genesis_car.
raulk Aug 26, 2024
707060b
size Vec with capacity.
raulk Aug 26, 2024
0ebe60f
rust fmt.
raulk Aug 26, 2024
29099f1
fix clippy.
raulk Aug 27, 2024
a3b3c4a
fix version; allocate enough vec capacity.
raulk Aug 29, 2024
501a256
Merge branch 'main' into simple-genesis
cryptoAtwill Aug 29, 2024
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
9 changes: 9 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ serde_yaml = { version = "0.9" }
serde_tuple = "0.5"
serde_with = "2.3"
serial_test = "3.0"
snap = "1.1.0"
strum = { version = "0.26.1", features = ["derive"] }
tempfile = "3.7"
thiserror = "1"
Expand Down
25 changes: 25 additions & 0 deletions fendermint/app/options/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ pub struct GenesisAddValidatorArgs {

#[derive(Args, Debug)]
pub struct GenesisIntoTendermintArgs {
/// The initial app bytes path for cometbft
#[arg(long, short)]
pub app_state: Option<PathBuf>,
/// Output file name for the Tendermint genesis JSON file.
#[arg(long, short)]
pub out: PathBuf,
Expand All @@ -147,6 +150,28 @@ pub enum GenesisIpcCommands {
Gateway(GenesisIpcGatewayArgs),
/// Fetch the genesis parameters of a subnet from the parent.
FromParent(Box<GenesisFromParentArgs>),
/// Seal the genesis state from the genesis parameter file
SealGenesis(SealGenesisArgs),
}

#[derive(Args, Debug, Clone)]
pub struct SealGenesisArgs {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
pub struct SealGenesisArgs {
pub struct SealGenesisStateArgs {

maybe?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is fine as it is.

/// The built in actors bundle path
#[arg(long, short)]
pub builtin_actors_path: PathBuf,

/// The custom actors bundle path
#[arg(long, short)]
pub custom_actors_path: PathBuf,

/// The solidity artifacts output path. If you are using ipc-monorepo, it should be the `out` folder
/// of `make build`
#[arg(long, short)]
pub artifacts_path: Option<PathBuf>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this an Option? It does not add up with the comments here? Are we loading them as embedded resources?


/// The sealed genesis state output path, i.e. finalized genesis state CAR file dump path
#[arg(long, short)]
pub output_path: PathBuf,
}

#[derive(Args, Debug, Clone)]
Expand Down
12 changes: 1 addition & 11 deletions fendermint/app/settings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,10 +263,6 @@ pub struct Settings {
snapshots_dir: PathBuf,
/// Solidity contracts.
contracts_dir: PathBuf,
/// Builtin-actors CAR file.
builtin_actors_bundle: PathBuf,
/// Custom actors CAR file.
custom_actors_bundle: PathBuf,

/// Where to reach CometBFT for queries or broadcasting transactions.
tendermint_rpc_url: Url,
Expand All @@ -291,13 +287,7 @@ pub struct Settings {
}

impl Settings {
home_relative!(
data_dir,
snapshots_dir,
contracts_dir,
builtin_actors_bundle,
custom_actors_bundle
);
home_relative!(data_dir, snapshots_dir, contracts_dir);

/// Load the default configuration from a directory,
/// then potential overrides specific to the run mode,
Expand Down
83 changes: 18 additions & 65 deletions fendermint/app/src/app.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
use std::future::Future;
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::{anyhow, Context, Result};
Expand All @@ -19,14 +18,15 @@ use fendermint_vm_interpreter::bytes::{
};
use fendermint_vm_interpreter::chain::{ChainEnv, ChainMessageApplyRet, IllegalMessage};
use fendermint_vm_interpreter::fvm::state::{
empty_state_tree, CheckStateRef, FvmExecState, FvmGenesisState, FvmQueryState, FvmStateParams,
empty_state_tree, CheckStateRef, FvmExecState, FvmQueryState, FvmStateParams,
FvmUpdatableParams,
};
use fendermint_vm_interpreter::fvm::store::ReadOnlyBlockstore;
use fendermint_vm_interpreter::fvm::{FvmApplyRet, FvmGenesisOutput, PowerUpdates};
use fendermint_vm_interpreter::fvm::{FvmApplyRet, PowerUpdates};
use fendermint_vm_interpreter::genesis::{read_genesis_car, GenesisAppState};
use fendermint_vm_interpreter::signed::InvalidSignature;
use fendermint_vm_interpreter::{
CheckInterpreter, ExecInterpreter, GenesisInterpreter, ProposalInterpreter, QueryInterpreter,
CheckInterpreter, ExecInterpreter, ProposalInterpreter, QueryInterpreter,
};
use fendermint_vm_message::query::FvmQueryHeight;
use fendermint_vm_snapshot::{SnapshotClient, SnapshotError};
Expand Down Expand Up @@ -109,12 +109,6 @@ pub struct AppConfig<S: KVStore> {
pub state_hist_namespace: S::Namespace,
/// Size of state history to keep; 0 means unlimited.
pub state_hist_size: u64,
/// Path to the Wasm bundle.
///
/// Only loaded once during genesis; later comes from the [`StateTree`].
pub builtin_actors_bundle: PathBuf,
/// Path to the custom actor WASM bundle.
pub custom_actors_bundle: PathBuf,
/// Block height where we should gracefully stop the node
pub halt_height: i64,
}
Expand All @@ -136,12 +130,6 @@ where
state_store: Arc<SS>,
/// Wasm engine cache.
multi_engine: Arc<MultiEngine>,
/// Path to the Wasm bundle.
///
/// Only loaded once during genesis; later comes from the [`StateTree`].
builtin_actors_bundle: PathBuf,
/// Path to the custom actor WASM bundle.
custom_actors_bundle: PathBuf,
/// Block height where we should gracefully stop the node
halt_height: i64,
/// Namespace to store app state.
Expand Down Expand Up @@ -195,8 +183,6 @@ where
db: Arc::new(db),
state_store: Arc::new(state_store),
multi_engine: Arc::new(MultiEngine::new(1)),
builtin_actors_bundle: config.builtin_actors_bundle,
custom_actors_bundle: config.custom_actors_bundle,
halt_height: config.halt_height,
namespace: config.app_namespace,
state_hist: KVCollection::new(config.state_hist_namespace),
Expand Down Expand Up @@ -390,6 +376,14 @@ where
// It's really the empty state tree that would be the best indicator.
!(height == 0 && params.timestamp.0 == 0 && params.network_version == NetworkVersion::V0)
}

fn parse_genesis_app_bytes(bytes: &[u8]) -> Result<Vec<u8>> {
// cometbft serves data in json format, convert from json string
match serde_json::from_slice(bytes)? {
serde_json::Value::String(s) => Ok(GenesisAppState::decode_and_decompress(&s)?),
_ => Err(anyhow!("invalid app state json")),
}
}
}

// NOTE: The `Application` interface doesn't allow failures at the moment. The protobuf
Expand All @@ -408,11 +402,6 @@ where
S::Namespace: Sync + Send,
DB: KVWritable<S> + KVReadable<S> + Clone + Send + Sync + 'static,
SS: Blockstore + Clone + Send + Sync + 'static,
I: GenesisInterpreter<
State = FvmGenesisState<SS>,
Genesis = Vec<u8>,
Output = FvmGenesisOutput,
>,
I: ProposalInterpreter<State = ChainEnv, Message = Vec<u8>>,
I: ExecInterpreter<
State = (ChainEnv, FvmExecState<SS>),
Expand Down Expand Up @@ -450,45 +439,18 @@ where

/// Called once upon genesis.
async fn init_chain(&self, request: request::InitChain) -> AbciResult<response::InitChain> {
let bundle = &self.builtin_actors_bundle;
let bundle = std::fs::read(bundle)
.map_err(|e| anyhow!("failed to load builtin bundle CAR from {bundle:?}: {e}"))?;

let custom_actors_bundle = &self.custom_actors_bundle;
let custom_actors_bundle = std::fs::read(custom_actors_bundle).map_err(|e| {
anyhow!("failed to load custom actor bundle CAR from {custom_actors_bundle:?}: {e}")
})?;

let state = FvmGenesisState::new(
self.state_store_clone(),
self.multi_engine.clone(),
&bundle,
&custom_actors_bundle,
)
.await
.context("failed to create genesis state")?;

tracing::info!(
manifest_root = format!("{}", state.manifest_data_cid),
"pre-genesis state created"
);

let genesis_bytes = request.app_state_bytes.to_vec();
let genesis_bytes = Self::parse_genesis_app_bytes(&request.app_state_bytes)?;
let genesis_hash =
fendermint_vm_message::cid(&genesis_bytes).context("failed to compute genesis CID")?;

// Make it easy to spot any discrepancies between nodes.
tracing::info!(genesis_hash = genesis_hash.to_string(), "genesis");

let (state, out) = self
.interpreter
.init(state, genesis_bytes)
.await
.context("failed to init from genesis")?;

let state_root = state.commit().context("failed to commit genesis state")?;
let (validators, state_params) = read_genesis_car(genesis_bytes, &self.state_store).await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, ideally we should be able to get validators by calling a getter on the gateway, so that we don't have to carry them separately. But the problem is that the Gateway doesn't store pubkeys; we should extend it for that.

let validators =
to_validator_updates(out.validators).context("failed to convert validators")?;
to_validator_updates(validators).context("failed to convert validators")?;

tracing::info!(state_params = serde_json::to_string(&state_params)?);

// Let's pretend that the genesis state is that of a fictive block at height 0.
// The record will be stored under height 1, and the record after the application
Expand All @@ -505,16 +467,7 @@ where
let app_state = AppState {
block_height: height,
oldest_state_height: height,
state_params: FvmStateParams {
state_root,
timestamp: out.timestamp,
network_version: out.network_version,
base_fee: out.base_fee,
circ_supply: out.circ_supply,
chain_id: out.chain_id.into(),
power_scale: out.power_scale,
app_version: 0,
},
state_params,
};

let response = response::InitChain {
Expand Down
29 changes: 27 additions & 2 deletions fendermint/app/src/cmd/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use fendermint_vm_genesis::{
ipc, Account, Actor, ActorMeta, Collateral, Genesis, Multisig, PermissionMode, SignerAddr,
Validator, ValidatorKey,
};
use fendermint_vm_interpreter::genesis::{GenesisAppState, GenesisBuilder};

use crate::cmd;
use crate::options::genesis::*;
Expand Down Expand Up @@ -94,6 +95,8 @@ cmd! {
set_ipc_gateway(&genesis_file, args),
GenesisIpcCommands::FromParent(args) =>
new_genesis_from_parent(&genesis_file, args).await,
GenesisIpcCommands::SealGenesis(args) =>
seal_genesis(&genesis_file, args).await,
}
}
}
Expand Down Expand Up @@ -213,7 +216,12 @@ fn set_eam_permissions(

fn into_tendermint(genesis_file: &PathBuf, args: &GenesisIntoTendermintArgs) -> anyhow::Result<()> {
let genesis = read_genesis(genesis_file)?;
let genesis_json = serde_json::to_value(&genesis)?;
let app_state: Option<String> = match args.app_state {
Some(ref path) if path.exists() => {
Some(GenesisAppState::v1(std::fs::read(path)?).compress_and_encode()?)
}
_ => None,
};

let chain_id: u64 = chainid::from_str_hashed(&genesis.chain_name)?.into();
let chain_id = chain_id.to_string();
Expand Down Expand Up @@ -248,7 +256,8 @@ fn into_tendermint(genesis_file: &PathBuf, args: &GenesisIntoTendermintArgs) ->
// Hopefully leaving this empty will skip validation,
// otherwise we have to run the genesis in memory here and now.
app_hash: tendermint::AppHash::default(),
app_state: genesis_json,
// cometbft serves data in json format, convert to string to be specific
app_state,
};
let tmg_json = serde_json::to_string_pretty(&tmg)?;
std::fs::write(&args.out, tmg_json)?;
Expand Down Expand Up @@ -280,6 +289,22 @@ fn set_ipc_gateway(genesis_file: &PathBuf, args: &GenesisIpcGatewayArgs) -> anyh
})
}

async fn seal_genesis(genesis_file: &PathBuf, args: &SealGenesisArgs) -> anyhow::Result<()> {
let genesis_params = read_genesis(genesis_file)?;

let mut builder = GenesisBuilder::new(
args.builtin_actors_path.clone(),
args.custom_actors_path.clone(),
genesis_params,
);

if let Some(ref ipc_system_artifacts) = args.artifacts_path {
builder = builder.with_ipc_system_contracts(ipc_system_artifacts.clone());
}

builder.write_to(args.output_path.clone()).await
}

async fn new_genesis_from_parent(
genesis_file: &PathBuf,
args: &GenesisFromParentArgs,
Expand Down
3 changes: 0 additions & 3 deletions fendermint/app/src/cmd/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ async fn run(settings: Settings) -> anyhow::Result<()> {
let interpreter = FvmMessageInterpreter::<NamespaceBlockstore, _>::new(
tendermint_client.clone(),
validator_ctx,
settings.contracts_dir(),
settings.fvm.gas_overestimation_rate,
settings.fvm.gas_search_step,
settings.fvm.exec_in_check,
Expand Down Expand Up @@ -300,8 +299,6 @@ async fn run(settings: Settings) -> anyhow::Result<()> {
app_namespace: ns.app,
state_hist_namespace: ns.state_hist,
state_hist_size: settings.db.state_hist_size,
builtin_actors_bundle: settings.builtin_actors_bundle(),
custom_actors_bundle: settings.custom_actors_bundle(),
halt_height: settings.halt_height,
},
db,
Expand Down
2 changes: 2 additions & 0 deletions fendermint/app/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
extern crate core;

// Copyright 2022-2024 Protocol Labs
// SPDX-License-Identifier: Apache-2.0, MIT
mod app;
Expand Down
2 changes: 1 addition & 1 deletion fendermint/testing/contract-test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fendermint_vm_core = { path = "../../vm/core" }
fendermint_vm_genesis = { path = "../../vm/genesis" }
fendermint_vm_message = { path = "../../vm/message" }
fendermint_vm_interpreter = { path = "../../vm/interpreter", features = [
"bundle",
"bundle", "test-util"
] }

[dev-dependencies]
Expand Down
Loading
Loading