Skip to content

Commit

Permalink
Define a genesis config file
Browse files Browse the repository at this point in the history
This aims to separate onchain data, which must be the same for all
nodes (chain ID, base fee, etc) from node-specific configuration.
Node configuration continues to be done via environment variables,
whereas onchain data is defined in a configuration file which we
can distribute to all node operators when launching a network. This
should greatly simplify coordination and reduce the frequency of
errors due to misconfigured nodes.
  • Loading branch information
jbearer committed May 9, 2024
1 parent 1db3846 commit 7f76026
Show file tree
Hide file tree
Showing 16 changed files with 335 additions and 129 deletions.
6 changes: 2 additions & 4 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,15 @@ ESPRESSO_SEQUENCER1_API_PORT=44001
ESPRESSO_SEQUENCER2_API_PORT=44002
ESPRESSO_SEQUENCER3_API_PORT=44003
ESPRESSO_SEQUENCER4_API_PORT=44004
ESPRESSO_SEQUENCER_MAX_BLOCK_SIZE=1mb
ESPRESSO_SEQUENCER_BASE_FEE=1
ESPRESSO_SEQUENCER_URL=http://sequencer0:${ESPRESSO_SEQUENCER_API_PORT}
ESPRESSO_SEQUENCER_STORAGE_PATH=/store/sequencer
ESPRESSO_SEQUENCER_GENESIS_FILE=/genesis
ESPRESSO_SEQUENCER_L1_PORT=8545
ESPRESSO_SEQUENCER_L1_WS_PORT=8546
ESPRESSO_SEQUENCER_L1_PROVIDER=http://demo-l1-network:${ESPRESSO_SEQUENCER_L1_PORT}
# Only allow 1 block to be processed for events at a time, simulating a very bad L1 provider.
ESPRESSO_SEQUENCER_L1_EVENTS_MAX_BLOCK_RANGE=1
ESPRESSO_SEQUENCER_ETH_MNEMONIC="test test test test test test test test test test test junk"
# The first account is the permission less builder, the last are sequencer0 to 4
ESPRESSO_SEQUENCER_PREFUNDED_BUILDER_ACCOUNTS=0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f
ESPRESSO_COMMITMENT_TASK_PORT=60000
ESPRESSO_SEQUENCER0_DB_PORT=5432
ESPRESSO_SEQUENCER1_DB_PORT=5433
Expand Down Expand Up @@ -104,6 +101,7 @@ ESPRESSO_BUILDER_INIT_NODE_COUNT=$ESPRESSO_ORCHESTRATOR_NUM_NODES
ESPRESSO_BUILDER_BOOTSTRAPPED_VIEW=0
ESPRESSO_BUILDER_WEBSERVER_RESPONSE_TIMEOUT_DURATION=1500ms
ESPRESSO_BUILDER_BUFFER_VIEW_NUM_COUNT=50
ESPRESSO_BUILDER_GENESIS_FILE=$ESPRESSO_SEQUENCER_GENESIS_FILE

# Load generator
ESPRESSO_SUBMIT_TRANSACTIONS_DELAY=2s
Expand Down
29 changes: 7 additions & 22 deletions builder/src/bin/permissioned-builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use hotshot_types::light_client::StateSignKey;
use hotshot_types::signature_key::BLSPrivKey;
use hotshot_types::traits::metrics::NoMetrics;
use hotshot_types::traits::node_implementation::ConsensusTime;
use sequencer::eth_signature_key::EthKeyPair;
use sequencer::persistence::no_storage::NoStorage;
use sequencer::{options::parse_size, BuilderParams, L1Params, NetworkParams};
use sequencer::{eth_signature_key::EthKeyPair, Genesis};
use sequencer::{L1Params, NetworkParams};
use snafu::Snafu;
use std::net::ToSocketAddrs;
use std::num::NonZeroUsize;
Expand All @@ -21,10 +21,6 @@ use url::Url;

#[derive(Parser, Clone, Debug)]
pub struct PermissionedBuilderOptions {
/// Unique identifier for this instance of the sequencer network.
#[clap(long, env = "ESPRESSO_SEQUENCER_CHAIN_ID", default_value = "0")]
pub chain_id: u16,

/// URL of the HotShot orchestrator.
#[clap(
short,
Expand Down Expand Up @@ -80,6 +76,10 @@ pub struct PermissionedBuilderOptions {
)]
pub webserver_poll_interval: Duration,

/// Path to TOML file containing genesis state.
#[clap(long, name = "GENESIS_FILE", env = "ESPRESSO_BUILDER_GENESIS_FILE")]
pub genesis_file: PathBuf,

/// Path to file containing private keys.
///
/// The file should follow the .env format, with two keys:
Expand Down Expand Up @@ -129,10 +129,6 @@ pub struct PermissionedBuilderOptions {
#[clap(long, env = "ESPRESSO_SEQUENCER_STATE_PEERS", value_delimiter = ',')]
pub state_peers: Vec<Url>,

/// Maximum size in bytes of a block
#[clap(long, env = "ESPRESSO_SEQUENCER_MAX_BLOCK_SIZE", value_parser = parse_size)]
pub max_block_size: u64,

/// Port to run the builder server on.
#[clap(short, long, env = "ESPRESSO_BUILDER_SERVER_PORT")]
pub port: u16,
Expand Down Expand Up @@ -174,10 +170,6 @@ pub struct PermissionedBuilderOptions {
/// Whether or not we are a DA node.
#[clap(long, env = "ESPRESSO_SEQUENCER_IS_DA", action)]
pub is_da: bool,

/// Base Fee for a block
#[clap(long, env = "ESPRESSO_BUILDER_BLOCK_BASE_FEE", default_value = "0")]
base_fee: u64,
}

#[derive(Clone, Debug, Snafu)]
Expand Down Expand Up @@ -226,16 +218,11 @@ async fn main() -> anyhow::Result<()> {

let l1_params = L1Params {
url: opt.l1_provider_url,
finalized_block: None,
events_max_block_range: 10000,
};

let builder_key_pair = EthKeyPair::from_mnemonic(&opt.eth_mnemonic, opt.eth_account_index)?;

let builder_params = BuilderParams {
prefunded_accounts: vec![],
};

// Parse supplied Libp2p addresses to their socket form
// We expect all nodes to be reachable via IPv4, so we filter out any IPv6 addresses.
// Downstream in HotShot we pin the IP address to v4, but this can be fixed in the future.
Expand Down Expand Up @@ -277,9 +264,9 @@ async fn main() -> anyhow::Result<()> {

// it will internally spawn the builder web server
let ctx = init_node(
Genesis::from_file(&opt.genesis_file)?,
network_params,
&NoMetrics,
builder_params,
l1_params,
builder_server_url.clone(),
builder_key_pair,
Expand All @@ -291,8 +278,6 @@ async fn main() -> anyhow::Result<()> {
buffer_view_num_count,
opt.is_da,
txn_timeout_duration,
opt.base_fee,
opt.max_block_size,
)
.await?;

Expand Down
21 changes: 8 additions & 13 deletions builder/src/bin/permissionless-builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use cld::ClDuration;
use es_version::SEQUENCER_VERSION;
use hotshot_types::data::ViewNumber;
use hotshot_types::traits::node_implementation::ConsensusTime;
use sequencer::L1Params;
use sequencer::{eth_signature_key::EthKeyPair, options::parse_size};
use sequencer::eth_signature_key::EthKeyPair;
use sequencer::{Genesis, L1Params};
use snafu::Snafu;
use std::num::NonZeroUsize;
use std::{str::FromStr, time::Duration};
use std::{path::PathBuf, str::FromStr, time::Duration};
use url::Url;

#[derive(Parser, Clone, Debug)]
Expand Down Expand Up @@ -42,10 +42,6 @@ struct NonPermissionedBuilderOptions {
#[clap(long, env = "ESPRESSO_SEQUENCER_STATE_PEERS", value_delimiter = ',')]
state_peers: Vec<Url>,

/// Maximum size in bytes of a block
#[clap(long, env = "ESPRESSO_SEQUENCER_MAX_BLOCK_SIZE", value_parser = parse_size)]
pub max_block_size: u64,

/// Port to run the builder server on.
#[clap(short, long, env = "ESPRESSO_BUILDER_SERVER_PORT")]
port: u16,
Expand Down Expand Up @@ -80,9 +76,9 @@ struct NonPermissionedBuilderOptions {
)]
buffer_view_num_count: usize,

/// Base Fee for a block
#[clap(long, env = "ESPRESSO_BUILDER_BLOCK_BASE_FEE", default_value = "0")]
base_fee: u64,
/// Path to TOML file containing genesis state.
#[clap(long, name = "GENESIS_FILE", env = "ESPRESSO_BUILDER_GENESIS_FILE")]
genesis_file: PathBuf,
}

#[derive(Clone, Debug, Snafu)]
Expand All @@ -104,12 +100,12 @@ async fn main() -> anyhow::Result<()> {
setup_backtrace();

let opt = NonPermissionedBuilderOptions::parse();
let genesis = Genesis::from_file(&opt.genesis_file)?;

let sequencer_version = SEQUENCER_VERSION;

let l1_params = L1Params {
url: opt.l1_provider_url,
finalized_block: None,
events_max_block_range: 10000,
};

Expand All @@ -119,9 +115,9 @@ async fn main() -> anyhow::Result<()> {
let builder_server_url: Url = format!("http://0.0.0.0:{}", opt.port).parse().unwrap();

let instance_state = build_instance_state(
genesis.chain_config,
l1_params,
opt.state_peers,
opt.max_block_size,
sequencer_version,
)
.unwrap();
Expand All @@ -144,7 +140,6 @@ async fn main() -> anyhow::Result<()> {
api_response_timeout_duration,
buffer_view_num_count,
txn_timeout_duration,
opt.base_fee,
)
.await;

Expand Down
4 changes: 1 addition & 3 deletions builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use sequencer::{
state::FeeAccount,
state::ValidatedState,
state_signature::{static_stake_table_commitment, StateSigner},
BuilderParams, L1Params, NetworkParams, Node, NodeState, PrivKey, PubKey, SeqTypes,
L1Params, NetworkParams, Node, NodeState, PrivKey, PubKey, SeqTypes,
};
use std::{alloc::System, any, fmt::Debug, mem};
use std::{marker::PhantomData, net::IpAddr};
Expand Down Expand Up @@ -567,7 +567,6 @@ pub mod testing {
Duration::from_millis(2000),
15,
Duration::from_millis(500),
0,
)
.await
.unwrap();
Expand Down Expand Up @@ -632,7 +631,6 @@ pub mod testing {
Duration::from_millis(2000),
15,
Duration::from_millis(500),
0,
)
.await
.unwrap();
Expand Down
16 changes: 10 additions & 6 deletions builder/src/non_permissioned.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::Context;
use async_broadcast::{
broadcast, Receiver as BroadcastReceiver, RecvError, Sender as BroadcastSender, TryRecvError,
};
Expand Down Expand Up @@ -33,8 +34,8 @@ use hotshot_types::{
utils::BuilderCommitment,
};
use sequencer::{
catchup::StatePeers, eth_signature_key::EthKeyPair, l1_client::L1Client, BuilderParams,
ChainConfig, L1Params, NetworkParams, NodeState, Payload, PrivKey, PubKey, SeqTypes,
catchup::StatePeers, eth_signature_key::EthKeyPair, l1_client::L1Client, ChainConfig, L1Params,
NetworkParams, NodeState, Payload, PrivKey, PubKey, SeqTypes,
};

use hotshot_events_service::{
Expand All @@ -57,9 +58,9 @@ pub struct BuilderConfig {
}

pub fn build_instance_state<Ver: StaticVersionType + 'static>(
chain_config: ChainConfig,
l1_params: L1Params,
state_peers: Vec<Url>,
max_block_size: u64,
_: Ver,
) -> anyhow::Result<NodeState> {
let l1_client = L1Client::new(
Expand All @@ -69,7 +70,7 @@ pub fn build_instance_state<Ver: StaticVersionType + 'static>(
);
let instance_state = NodeState::new(
u64::MAX, // dummy node ID, only used for debugging
ChainConfig::new(0, max_block_size, 0),
chain_config,
l1_client,
Arc::new(StatePeers::<Ver>::from_urls(state_peers)),
);
Expand All @@ -89,7 +90,6 @@ impl BuilderConfig {
max_api_timeout_duration: Duration,
buffered_view_num_count: usize,
maximize_txns_count_timeout_duration: Duration,
base_fee: u64,
) -> anyhow::Result<Self> {
// tx channel
let (tx_sender, tx_receiver) = broadcast::<MessageType<SeqTypes>>(channel_capacity.get());
Expand Down Expand Up @@ -151,7 +151,11 @@ impl BuilderConfig {
bootstrapped_view,
buffered_view_num_count as u64,
maximize_txns_count_timeout_duration,
base_fee,
instance_state
.chain_config
.base_fee()
.as_u64()
.context("the base fee exceeds the maximum amount that a builder can pay (defined by u64::MAX)")?,
Arc::new(instance_state),
);

Expand Down
32 changes: 17 additions & 15 deletions builder/src/permissioned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ use sequencer::{
state::FeeAccount,
state::ValidatedState,
state_signature::{static_stake_table_commitment, StateSigner},
BuilderParams, L1Params, NetworkParams, Node, NodeState, Payload, PrivKey, PubKey, SeqTypes,
Genesis, L1Params, NetworkParams, Node, NodeState, Payload, PrivKey, PubKey, SeqTypes,
};
use std::{alloc::System, any, fmt::Debug, mem};
use std::{marker::PhantomData, net::IpAddr};
Expand Down Expand Up @@ -129,9 +129,9 @@ pub struct BuilderContext<

#[allow(clippy::too_many_arguments)]
pub async fn init_node<P: SequencerPersistence, Ver: StaticVersionType + 'static>(
genesis: Genesis,
network_params: NetworkParams,
metrics: &dyn Metrics,
builder_params: BuilderParams,
l1_params: L1Params,
hotshot_builder_api_url: Url,
eth_key_pair: EthKeyPair,
Expand All @@ -143,8 +143,6 @@ pub async fn init_node<P: SequencerPersistence, Ver: StaticVersionType + 'static
buffered_view_num_count: usize,
is_da: bool,
maximize_txns_count_timeout_duration: Duration,
base_fee: u64,
max_block_size: u64,
) -> anyhow::Result<BuilderContext<network::Production, P, Ver>> {
// Orchestrator client
let validator_args = ValidatorArgs {
Expand Down Expand Up @@ -244,9 +242,9 @@ pub async fn init_node<P: SequencerPersistence, Ver: StaticVersionType + 'static
let _ = NetworkingMetricsValue::new(metrics);

let mut genesis_state = ValidatedState::default();
for address in builder_params.prefunded_accounts {
tracing::warn!("Prefunding account {:?} for demo", address);
genesis_state.prefund_account(address.into(), U256::max_value().into());
for (address, amount) in genesis.accounts {
tracing::warn!(%address, %amount, "Prefunding account for demo");
genesis_state.prefund_account(address, amount);
}

let l1_client = L1Client::new(
Expand All @@ -255,12 +253,14 @@ pub async fn init_node<P: SequencerPersistence, Ver: StaticVersionType + 'static
l1_params.events_max_block_range,
);

let instance_state = NodeState::new(
node_index,
ChainConfig::new(0, max_block_size, 0),
let instance_state = NodeState {
chain_config: genesis.chain_config,
l1_client,
Arc::new(StatePeers::<Ver>::from_urls(network_params.state_peers)),
);
genesis_state,
l1_genesis: genesis.l1_finalized,
peers: Arc::new(StatePeers::<Ver>::from_urls(network_params.state_peers)),
node_id: node_index,
};

let stake_table_commit =
static_stake_table_commitment(&config.config.known_nodes_with_stake, STAKE_TABLE_CAPACITY);
Expand Down Expand Up @@ -291,7 +291,6 @@ pub async fn init_node<P: SequencerPersistence, Ver: StaticVersionType + 'static
max_api_timeout_duration,
buffered_view_num_count,
maximize_txns_count_timeout_duration,
base_fee,
)
.await?;

Expand Down Expand Up @@ -387,7 +386,6 @@ impl<N: network::Type, P: SequencerPersistence, Ver: StaticVersionType + 'static
max_api_timeout_duration: Duration,
buffered_view_num_count: usize,
maximize_txns_count_timeout_duration: Duration,
base_fee: u64,
) -> anyhow::Result<Self> {
// tx channel
let (tx_sender, tx_receiver) = broadcast::<MessageType<SeqTypes>>(channel_capacity.get());
Expand Down Expand Up @@ -449,7 +447,11 @@ impl<N: network::Type, P: SequencerPersistence, Ver: StaticVersionType + 'static
bootstrapped_view,
buffered_view_num_count as u64,
maximize_txns_count_timeout_duration,
base_fee,
instance_state
.chain_config
.base_fee()
.as_u64()
.context("the base fee exceeds the maximum amount that a builder can pay (defined by u64::MAX)")?,
Arc::new(instance_state),
);

Expand Down
8 changes: 8 additions & 0 deletions data/genesis.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[chain_config]
chain_id = 0
base_fee = 1
max_block_size = '1mb'

[accounts]
# Permissionless builder
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f = 1000000000
Loading

0 comments on commit 7f76026

Please sign in to comment.