Skip to content
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- Refactored NTX Builder startup and introduced `NtxBuilderConfig` with configurable parameters ([#1610](https://github.com/0xMiden/miden-node/pull/1610)).
- Refactored NTX Builder actor state into `AccountDeltaTracker` and `NotePool` for clarity, and added tracing instrumentation to event broadcasting ([#1611](https://github.com/0xMiden/miden-node/pull/1611)).
- Add #[track_caller] to tracing/logging helpers ([#1651](https://github.com/0xMiden/miden-node/pull/1651)).
- Added support for generic account loading at genesis ([#1624](https://github.com/0xMiden/miden-node/pull/1624)).

## v0.13.5 (TBD)

Expand Down
2 changes: 2 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 @@ -86,6 +86,7 @@ rand = { version = "0.9" }
rand_chacha = { version = "0.9" }
rstest = { version = "0.26" }
serde = { features = ["derive"], version = "1" }
tempfile = { version = "3" }
thiserror = { default-features = false, version = "2.0" }
tokio = { features = ["rt-multi-thread"], version = "1.46" }
tokio-stream = { version = "0.1" }
Expand Down
3 changes: 1 addition & 2 deletions bin/node/src/commands/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ impl StoreCommand {
// Parse genesis config (or default if not given).
let config = genesis_config
.map(|file_path| {
let toml_str = fs_err::read_to_string(file_path)?;
GenesisConfig::read_toml(toml_str.as_str()).with_context(|| {
GenesisConfig::read_toml_file(file_path).with_context(|| {
Copy link
Contributor

Choose a reason for hiding this comment

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

This swallows some errors, i.e. missing, access rights

format!("failed to parse genesis config from file {}", file_path.display())
})
})
Expand Down
2 changes: 1 addition & 1 deletion crates/block-producer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ pretty_assertions = "1.4"
rand_chacha = { default-features = false, version = "0.9" }
rstest = { workspace = true }
serial_test = "3.2"
tempfile = { version = "3.20" }
tempfile = { workspace = true }
tokio = { features = ["test-util"], workspace = true }
winterfell = { version = "0.13" }
2 changes: 1 addition & 1 deletion crates/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ miden-protocol = { default-features = true, features = ["testing"], workspace
miden-standards = { workspace = true }
reqwest = { version = "0.12" }
rstest = { workspace = true }
tempfile = { version = "3.20" }
tempfile = { workspace = true }
4 changes: 4 additions & 0 deletions crates/store/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ tracing = { workspace = true }
url = { workspace = true }

[build-dependencies]
fs-err = { workspace = true }
miden-agglayer = { branch = "next", features = ["testing"], git = "https://github.com/0xMiden/miden-base" }
miden-node-rocksdb-cxx-linkage-fix = { workspace = true }
miden-protocol = { features = ["std"], workspace = true }

[dev-dependencies]
assert_matches = { workspace = true }
Expand All @@ -62,6 +65,7 @@ miden-protocol = { default-features = true, features = ["testing"], works
miden-standards = { features = ["testing"], workspace = true }
rand = { workspace = true }
regex = { version = "1.11" }
tempfile = { workspace = true }
termtree = { version = "0.5" }

[features]
Expand Down
94 changes: 94 additions & 0 deletions crates/store/build.rs
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are generating them if the accounts are checked-in? As a general rule build.rs should be used for out of tree code generation, not to generate code that gets checked in.

Copy link
Contributor

Choose a reason for hiding this comment

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

Out of scope: We should revisit how we deal protobuf generated code too.

Original file line number Diff line number Diff line change
@@ -1,12 +1,106 @@
// This build.rs is required to trigger the `diesel_migrations::embed_migrations!` proc-macro in
// `store/src/db/migrations.rs` to include the latest version of the migrations into the binary, see <https://docs.rs/diesel_migrations/latest/diesel_migrations/macro.embed_migrations.html#automatic-rebuilds>.

use std::path::PathBuf;
use std::sync::Arc;

use miden_agglayer::{create_existing_agglayer_faucet, create_existing_bridge_account};
use miden_protocol::account::{Account, AccountCode, AccountFile};
use miden_protocol::{Felt, Word};

fn main() {
println!("cargo:rerun-if-changed=./src/db/migrations");
// If we do one re-write, the default rules are disabled,
// hence we need to trigger explicitly on `Cargo.toml`.
// <https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed>
println!("cargo:rerun-if-changed=Cargo.toml");

// Generate sample agglayer account files for genesis config samples.
generate_agglayer_sample_accounts();
miden_node_rocksdb_cxx_linkage_fix::configure();
}

/// Generates sample agglayer account files for the `02-with-account-files` genesis config sample.
///
/// Creates:
/// - `bridge.mac` - agglayer bridge account
Copy link
Contributor

Choose a reason for hiding this comment

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

Did we document the .mac extension somewhere? miden-account-code?

/// - `agglayer_faucet_eth.mac` - agglayer faucet for wrapped ETH
/// - `agglayer_faucet_usdc.mac` - agglayer faucet for wrapped USDC
fn generate_agglayer_sample_accounts() {
// Use CARGO_MANIFEST_DIR to get the absolute path to the crate root
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
let samples_dir: PathBuf =
[&manifest_dir, "src", "genesis", "config", "samples", "02-with-account-files"]
.iter()
.collect();

// Create the directory if it doesn't exist
fs_err::create_dir_all(&samples_dir).expect("Failed to create samples directory");

// Use deterministic seeds for reproducible builds
// WARNING: DO NOT USE THIS IN PRODUCTION
let bridge_seed: Word = Word::new([Felt::new(1u64); 4]);
let eth_faucet_seed: Word = Word::new([Felt::new(2u64); 4]);
let usdc_faucet_seed: Word = Word::new([Felt::new(3u64); 4]);

// Create the bridge account first (faucets need to reference it)
// Use "existing" variant so accounts have nonce > 0 (required for genesis)
let bridge_account = create_existing_bridge_account(bridge_seed);
let bridge_account_id = bridge_account.id();

// Create AggLayer faucets using "existing" variant
// ETH: 18 decimals, max supply of 1 billion tokens
let eth_faucet = create_existing_agglayer_faucet(
eth_faucet_seed,
"ETH",
18,
Felt::new(1_000_000_000),
bridge_account_id,
);

// USDC: 6 decimals, max supply of 10 billion tokens
let usdc_faucet = create_existing_agglayer_faucet(
usdc_faucet_seed,
"USDC",
6,
Felt::new(10_000_000_000),
bridge_account_id,
);

// Strip source location decorators from account code to ensure deterministic output.
let bridge_account = strip_code_decorators(bridge_account);
let eth_faucet = strip_code_decorators(eth_faucet);
let usdc_faucet = strip_code_decorators(usdc_faucet);

// Save account files (without secret keys since these use NoAuth)
let bridge_file = AccountFile::new(bridge_account, vec![]);
let eth_faucet_file = AccountFile::new(eth_faucet, vec![]);
let usdc_faucet_file = AccountFile::new(usdc_faucet, vec![]);

// Write files
bridge_file
.write(samples_dir.join("bridge.mac"))
.expect("Failed to write bridge.mac");
eth_faucet_file
.write(samples_dir.join("agglayer_faucet_eth.mac"))
.expect("Failed to write agglayer_faucet_eth.mac");
usdc_faucet_file
.write(samples_dir.join("agglayer_faucet_usdc.mac"))
.expect("Failed to write agglayer_faucet_usdc.mac");
}

/// Strips source location decorators from an account's code MAST forest.
///
/// This is necessary because the MAST forest embeds absolute file paths from the Cargo build
/// directory, which include a hash that differs between `cargo check` and `cargo build`. Stripping
/// decorators ensures the serialized `.mac` files are identical regardless of which cargo command
/// is used (CI or local builds or tests).
fn strip_code_decorators(account: Account) -> Account {
let (id, vault, storage, code, nonce, seed) = account.into_parts();

let mut mast = code.mast();
Arc::make_mut(&mut mast).strip_decorators();
let code = AccountCode::from_parts(mast, code.procedures().to_vec());

Account::new_unchecked(id, vault, storage, code, nonce, seed)
}
12 changes: 11 additions & 1 deletion crates/store/src/genesis/config/errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use miden_protocol::account::AccountId;
use miden_protocol::errors::{
AccountDeltaError,
Expand All @@ -17,13 +19,21 @@ use crate::genesis::config::TokenSymbolStr;
pub enum GenesisConfigError {
#[error(transparent)]
Toml(#[from] toml::de::Error),
#[error("failed to read config file at {path}: {reason}")]
ConfigFileRead { path: PathBuf, reason: String },
#[error("failed to read account file at {path}: {reason}")]
AccountFileRead { path: PathBuf, reason: String },
#[error("native faucet from file {path} is not a fungible faucet")]
NativeFaucetNotFungible { path: PathBuf },
#[error("account translation from config to state failed")]
Account(#[from] AccountError),
#[error("asset translation from config to state failed")]
Asset(#[from] AssetError),
#[error("adding assets to account failed")]
AccountDelta(#[from] AccountDeltaError),
#[error("the defined asset {symbol:?} has no corresponding faucet")]
#[error(
"the defined asset {symbol:?} has no corresponding faucet, or the faucet was provided as an account file"
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should impl Fmt for TokenSymbolStr so we can do

Suggested change
"the defined asset {symbol:?} has no corresponding faucet, or the faucet was provided as an account file"
"the defined asset '{symbol}' has no corresponding faucet, or the faucet was provided as an account file"

)]
Comment on lines +34 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't understand how the faucet being specified as an account file is an error, but I'll return to this once I've read the rest.

MissingFaucetDefinition { symbol: TokenSymbolStr },
#[error("account with id {account_id} was referenced but is not part of given genesis state")]
MissingGenesisAccount { account_id: AccountId },
Expand Down
Loading
Loading