Skip to content

Commit 1461c11

Browse files
irnbbewakesprajwolrg
authored
feat(asm): integrate ASM v0.4.0 into Alpen main (#2378)
* chore(deps): bump strata-common to v0.4.0 * chore(deps): upgrade ASM and zkaleido to v0.4.0 Align host and checkpoint guest dependencies with strata-common v0.4.0. Enable native ASM host assembly and update SP1 dependencies and CI tooling to 6.8.1. * fix(tools): adapt ASM parameters and admin signing to v0.4.0 Generate network-specific P2WPKH admin signer addresses, adopt the updated safe-harbor fields, and pass the network to admin signing. Update parameter fixtures and cover signer address serialization. * feat(asm): integrate v0.4.0 worker with trusted execution parameters Load the genesis predicate and native execution catalog from standalone JSON parameters with private fields and read-only accessors. Use upstream worker assembly and MMR prefill, provide manifest lookup, and update Docker and functional-test setup with development parameters. * style: fix Cargo manifest formatting for Taplo * fix(config): update ASM execution catalog paths after relocation * perf(asm): batch the manifest MMR genesis prefill The v0.4.0 worker prefills the manifest MMR itself, and the trait's default writes one leaf per height, each in its own transaction. This brings back the slow startup that #2284 fixed: about 10 minutes on testnet-prod and 31 on mainnet-prod for a fresh datadir, before RPC and health checks come up. Override the hook to use the batched MMR helper. The worker still decides when to prefill, and the sentinel leaves are the same, so the MMR contents don't change. --------- Co-authored-by: Bibek Pandey <bibek@alpenlabs.io> Co-authored-by: Prajwol Gyawali <prajwol@alpenlabs.io>
1 parent eef78b2 commit 1461c11

32 files changed

Lines changed: 506 additions & 211 deletions

File tree

‎Cargo.lock‎

Lines changed: 69 additions & 75 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -160,56 +160,58 @@ strata-test-utils-ssz = { path = "crates/test-utils/ssz" }
160160
strata-zkvm-hosts = { path = "crates/zkvm/hosts" }
161161

162162
# strata-common
163-
strata-btc-types = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
163+
strata-btc-types = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
164164
strata-codec = { git = "https://github.com/alpenlabs/strata-common", features = [
165165
"derive",
166-
], tag = "v0.4.0-rc.3" }
167-
strata-codec-tests = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
168-
strata-crypto = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
169-
strata-db-macros = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
170-
strata-identifiers = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
171-
strata-l1-envelope-fmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
172-
strata-l1-txfmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
173-
strata-logging = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
166+
], tag = "v0.4.0" }
167+
strata-codec-tests = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
168+
strata-crypto = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
169+
strata-db-macros = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
170+
strata-identifiers = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
171+
strata-l1-envelope-fmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
172+
strata-l1-txfmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
173+
strata-logging = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
174174
strata-merkle = { git = "https://github.com/alpenlabs/strata-common", features = [
175175
"legacy_compact",
176-
], tag = "v0.4.0-rc.3" }
177-
strata-merkle-node-store = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
178-
strata-metrics = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
179-
strata-msg-fmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
180-
strata-ol-logs = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
176+
], tag = "v0.4.0" }
177+
strata-merkle-node-store = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
178+
strata-metrics = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
179+
strata-msg-fmt = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
180+
strata-ol-logs = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
181181
strata-predicate = { git = "https://github.com/alpenlabs/strata-common", features = [
182182
"serde",
183-
], tag = "v0.4.0-rc.3" }
184-
strata-rpc-tracing = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
185-
strata-service = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
186-
strata-tasks = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0-rc.3" }
183+
], tag = "v0.4.0" }
184+
strata-rpc-tracing = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
185+
strata-service = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
186+
strata-tasks = { git = "https://github.com/alpenlabs/strata-common", tag = "v0.4.0" }
187187

188188
# asm
189-
strata-asm-admin-threshold-sig = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
190-
strata-asm-admin-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
191-
strata-asm-bridge-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
192-
strata-asm-checkpoint-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
193-
strata-asm-common = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
194-
strata-asm-logs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
195-
strata-asm-manifest-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
196-
strata-asm-params = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
197-
strata-asm-proto-admin = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
198-
strata-asm-proto-admin-txs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
199-
strata-asm-proto-bridge = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
200-
strata-asm-proto-bridge-msgs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
201-
strata-asm-proto-bridge-txs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
202-
strata-asm-proto-checkpoint = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
203-
strata-asm-proto-checkpoint-msgs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
204-
strata-asm-proto-checkpoint-txs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
205-
strata-asm-proto-txs-test-utils = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
206-
strata-asm-spec = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
207-
strata-asm-stf = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
208-
strata-asm-worker = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
209-
strata-btc-verification = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
210-
strata-checkpoint-verification = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
211-
strata-test-utils-btc = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
212-
strata-test-utils-checkpoint = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0-rc.6" }
189+
strata-asm-admin-threshold-sig = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
190+
strata-asm-admin-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
191+
strata-asm-bridge-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
192+
strata-asm-checkpoint-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
193+
strata-asm-common = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
194+
strata-asm-logs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
195+
strata-asm-manifest-types = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
196+
strata-asm-params = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
197+
strata-asm-proto-admin = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
198+
strata-asm-proto-admin-txs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
199+
strata-asm-proto-bridge = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
200+
strata-asm-proto-bridge-msgs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
201+
strata-asm-proto-bridge-txs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
202+
strata-asm-proto-checkpoint = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
203+
strata-asm-proto-checkpoint-msgs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
204+
strata-asm-proto-checkpoint-txs = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
205+
strata-asm-proto-txs-test-utils = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
206+
strata-asm-spec = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0", features = [
207+
"host",
208+
] }
209+
strata-asm-stf = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
210+
strata-asm-worker = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
211+
strata-btc-verification = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
212+
strata-checkpoint-verification = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
213+
strata-test-utils-btc = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
214+
strata-test-utils-checkpoint = { git = "https://github.com/alpenlabs/asm", tag = "v0.4.0" }
213215

214216
# sled wrapper
215217
typed-sled = { git = "https://github.com/alpenlabs/typed-sled" }
@@ -218,10 +220,10 @@ typed-sled = { git = "https://github.com/alpenlabs/typed-sled" }
218220
zkaleido = { git = "https://github.com/alpenlabs/zkaleido", features = [
219221
"arbitrary",
220222
"ssz",
221-
], tag = "v0.3.0" }
222-
zkaleido-native-adapter = { git = "https://github.com/alpenlabs/zkaleido", tag = "v0.3.0" }
223-
zkaleido-sp1-groth16-verifier = { git = "https://github.com/alpenlabs/zkaleido", tag = "v0.3.0" }
224-
zkaleido-sp1-host = { git = "https://github.com/alpenlabs/zkaleido", tag = "v0.3.0" }
223+
], tag = "v0.4.0" }
224+
zkaleido-native-adapter = { git = "https://github.com/alpenlabs/zkaleido", tag = "v0.4.0" }
225+
zkaleido-sp1-groth16-verifier = { git = "https://github.com/alpenlabs/zkaleido", tag = "v0.4.0" }
226+
zkaleido-sp1-host = { git = "https://github.com/alpenlabs/zkaleido", tag = "v0.4.0" }
225227

226228
make_buf = { git = "https://github.com/alpenlabs/make_buf", version = "1.0.2" }
227229

‎bin/datatool/Cargo.toml‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ hex.workspace = true
1919
rand_core.workspace = true
2020
serde.workspace = true
2121
serde_json.workspace = true
22-
strata-asm-admin-threshold-sig.workspace = true
2322
strata-asm-admin-types.workspace = true
2423
strata-asm-bridge-types.workspace = true
2524
strata-asm-params.workspace = true

‎bin/datatool/src/cmd/asm_params.rs‎

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ use std::{
77
str::FromStr,
88
};
99

10-
use bitcoin::{secp256k1::PublicKey, Network, XOnlyPublicKey};
10+
use bitcoin::{secp256k1::PublicKey, Address, CompressedPublicKey, Network, XOnlyPublicKey};
1111
use serde::Serialize;
12-
use strata_asm_admin_threshold_sig::{CompressedPublicKey, ThresholdConfig};
13-
use strata_asm_admin_types::ConfirmationDepths;
14-
use strata_asm_bridge_types::SafeHarbourAddress;
12+
use strata_asm_admin_types::{ConfirmationDepths, UncheckedThresholdConfig};
13+
use strata_asm_bridge_types::SafeHarborAddress;
1514
use strata_asm_params::{
1615
AdministrationInitConfig, AsmParams, BridgeInitConfig, CheckpointInitConfig,
1716
SubprotocolInstance,
@@ -92,14 +91,8 @@ pub(super) fn exec(cmd: SubcAsmParams, ctx: &mut CmdContext) -> anyhow::Result<(
9291
pubkeys.push(PublicKey::from_str(key.trim())?);
9392
}
9493

95-
// Build admin subprotocol params using the operator keys for all three admin roles.
96-
let admin_keys: Vec<CompressedPublicKey> = pubkeys
97-
.iter()
98-
.copied()
99-
.map(CompressedPublicKey::from)
100-
.collect();
101-
102-
let threshold = ThresholdConfig::try_new(admin_keys, NonZero::new(1).expect("1 is non-zero"))?;
94+
// Derive signer addresses on the anchor's network for all four admin roles.
95+
let threshold = admin_threshold_config(&pubkeys, anchor.network)?;
10396

10497
let depth = cmd.confirmation_depth.unwrap_or(DEFAULT_CONFIRMATION_DEPTH);
10598
let confirmation_depths = ConfirmationDepths {
@@ -113,7 +106,7 @@ pub(super) fn exec(cmd: SubcAsmParams, ctx: &mut CmdContext) -> anyhow::Result<(
113106
asm_stf_vk_update: depth,
114107
ee_stf_vk_update: depth,
115108
defcon3: depth,
116-
safe_harbour_address_update: depth,
109+
safe_harbor_address_update: depth,
117110
};
118111

119112
let admin = AdministrationInitConfig::new(
@@ -174,7 +167,7 @@ pub(super) fn exec(cmd: SubcAsmParams, ctx: &mut CmdContext) -> anyhow::Result<(
174167
operator_fee: BitcoinAmount::try_from(cmd.operator_fee.unwrap_or(DEFAULT_OPERATOR_FEE))
175168
.expect("amount must not exceed the Bitcoin money supply"),
176169
recovery_delay: cmd.recovery_delay.unwrap_or(DEFAULT_RECOVERY_DELAY),
177-
safe_harbour_address,
170+
safe_harbor_address: safe_harbour_address,
178171
};
179172

180173
// Assemble ASM params.
@@ -364,14 +357,28 @@ fn write_cli_network_profile(path: &Path, profile: &CliNetworkProfile) -> anyhow
364357
Ok(())
365358
}
366359

360+
fn admin_threshold_config(
361+
pubkeys: &[PublicKey],
362+
network: Network,
363+
) -> anyhow::Result<UncheckedThresholdConfig> {
364+
let signers = pubkeys
365+
.iter()
366+
.map(|key| Address::p2wpkh(&CompressedPublicKey(*key), network).into_unchecked())
367+
.collect();
368+
Ok(UncheckedThresholdConfig::try_new(
369+
signers,
370+
NonZero::new(1).expect("1 is non-zero"),
371+
)?)
372+
}
373+
367374
fn resolve_sequencer_key(seq_pk: Option<&str>) -> anyhow::Result<Buf32> {
368375
let pk_hex = seq_pk
369376
.ok_or_else(|| anyhow::anyhow!("--seq-pk is required by ASM checkpoint authentication"))?;
370377
let xonly = XOnlyPublicKey::from_str(pk_hex.trim())?;
371378
Ok(xonly.serialize().into())
372379
}
373380

374-
fn resolve_safe_harbour_address(descriptor: &str) -> anyhow::Result<SafeHarbourAddress> {
381+
fn resolve_safe_harbour_address(descriptor: &str) -> anyhow::Result<SafeHarborAddress> {
375382
let descriptor = descriptor.trim();
376383
anyhow::ensure!(
377384
!descriptor.is_empty(),
@@ -387,7 +394,7 @@ fn resolve_safe_harbour_address(descriptor: &str) -> anyhow::Result<SafeHarbourA
387394
descriptor.type_tag()
388395
);
389396

390-
SafeHarbourAddress::try_from(descriptor)
397+
SafeHarborAddress::try_from(descriptor)
391398
.map_err(|e| anyhow::anyhow!("invalid safe harbour descriptor: {e}"))
392399
}
393400

@@ -402,6 +409,28 @@ mod tests {
402409
/// via `genseqpubkey`.
403410
const TEST_SEQ_PK: &str = "14ebfa9a90fee3020686b5334b297b675a9f29282f44b6c3a4ab1f0582021839";
404411

412+
#[test]
413+
fn admin_signers_use_the_anchor_network_and_operator_key() {
414+
let key = PublicKey::from_str(
415+
"0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
416+
)
417+
.unwrap();
418+
for network in [Network::Bitcoin, Network::Signet, Network::Regtest] {
419+
let config = admin_threshold_config(&[key], network).unwrap();
420+
let json = serde_json::to_value(&config).unwrap();
421+
let address = config.signers()[0]
422+
.clone()
423+
.require_network(network)
424+
.unwrap();
425+
assert_eq!(address, Address::p2wpkh(&CompressedPublicKey(key), network));
426+
assert_eq!(json["signers"][0], address.to_string());
427+
assert_eq!(json["threshold"], 1);
428+
let decoded: UncheckedThresholdConfig = serde_json::from_value(json).unwrap();
429+
assert_eq!(decoded, config);
430+
}
431+
assert!(admin_threshold_config(&[], Network::Regtest).is_err());
432+
}
433+
405434
#[test]
406435
fn cli_network_profile_matches_cli_config_schema() {
407436
let profile = CliNetworkProfile {

‎bin/strata-test-cli/src/cmd/create_ee_predicate_update.rs‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,13 @@ fn create_signed_payload(
307307
seq_no: u64,
308308
admin_secret_key: &SecretKey,
309309
) -> SignedPayload {
310-
let signatures = create_signature_set(slice::from_ref(admin_secret_key), &[0], &action, seq_no);
310+
let signatures = create_signature_set(
311+
slice::from_ref(admin_secret_key),
312+
&[0],
313+
&action,
314+
seq_no,
315+
NETWORK,
316+
);
311317
SignedPayload::new(seq_no, action, signatures)
312318
}
313319

‎bin/strata/src/args.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ mod tests {
180180
fn test_config() -> Config {
181181
toml::from_str(
182182
r#"
183+
asm_execution = "asm-execution-params.json"
184+
183185
[bitcoind]
184186
rpc_url = "http://localhost:18332"
185187
rpc_user = "alpen"

‎bin/strata/src/bootstrap.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ mod tests {
657657
network: Network::Bitcoin,
658658
};
659659
let anchor_state = AnchorState {
660+
spec_id: 0,
660661
magic: AnchorState::magic_ssz(MagicBytes::from(*b"ALPN")),
661662
chain_view: ChainViewState {
662663
pow_state: HeaderVerificationState::init(l1_anchor),

‎bin/strata/src/context.rs‎

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use strata_asm_params::AsmParams;
1414
#[cfg(feature = "prover")]
1515
use strata_asm_params::SubprotocolInstance;
1616
use strata_config::{
17-
BitcoindConfig, BlockAssemblyConfig, Config, SequencerConfig, SequencerRuntimeConfig,
17+
AsmExecutionParams, BitcoindConfig, BlockAssemblyConfig, Config, SequencerConfig,
18+
SequencerRuntimeConfig,
1819
};
1920
#[cfg(feature = "prover")]
2021
use strata_config::{ProverBackend, ProverConfig};
@@ -70,6 +71,7 @@ pub(crate) fn init_node_context(
7071
.as_ref()
7172
.ok_or(InitError::MissingAsmParams)?;
7273
let asm_params = load_asm_params(asm_params_path)?;
74+
let asm_execution = load_asm_execution_params(&args.config, &config.asm_execution)?;
7375

7476
let blockasm_config = config
7577
.sequencer
@@ -106,6 +108,7 @@ pub(crate) fn init_node_context(
106108
handle,
107109
config,
108110
blockasm_config,
111+
asm_execution,
109112
Arc::new(asm_params),
110113
ol_params.into(),
111114
storage,
@@ -382,6 +385,20 @@ pub(crate) fn load_block_assembly_config(
382385
))))
383386
}
384387

388+
fn load_asm_execution_params(
389+
config_path: &Path,
390+
params_path: &Path,
391+
) -> Result<AsmExecutionParams, InitError> {
392+
let path = config_path
393+
.parent()
394+
.unwrap_or_else(|| Path::new("."))
395+
.join(params_path);
396+
let json = fs::read_to_string(&path)
397+
.map_err(|source| InitError::AsmExecutionParamsRead { path, source })?;
398+
serde_json::from_str(&json)
399+
.map_err(|err| InitError::UnparsableParamsFile(SerdeError::new(json, err)))
400+
}
401+
385402
fn load_asm_params(path: &Path) -> Result<AsmParams, InitError> {
386403
let json = fs::read_to_string(path)?;
387404
let asm_params =
@@ -511,7 +528,7 @@ mod shared_network_params_tests {
511528
"assignment_duration": 0,
512529
"operator_fee": 0,
513530
"recovery_delay": 0,
514-
"safe_harbour_address": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
531+
"safe_harbor_address": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"
515532
}}
516533
}}
517534
]
@@ -813,11 +830,57 @@ mod tests {
813830
use strata_storage::{create_node_storage, test_runtime_handle};
814831

815832
use super::{
816-
ensure_ol_genesis, load_block_assembly_config, load_sequencer_runtime_config,
817-
resolve_default_sequencer_config_path,
833+
ensure_ol_genesis, load_asm_execution_params, load_block_assembly_config,
834+
load_sequencer_runtime_config, resolve_default_sequencer_config_path,
818835
};
819836
use crate::errors::InitError;
820837

838+
#[test]
839+
fn example_config_execution_params_load() {
840+
let config_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../example_config.toml");
841+
let config: Config = toml::from_str(&fs::read_to_string(&config_path).unwrap()).unwrap();
842+
load_asm_execution_params(&config_path, &config.asm_execution)
843+
.expect("example config must reference valid checked-in execution parameters");
844+
}
845+
846+
#[test]
847+
fn execution_params_resolve_relative_to_node_config() {
848+
let dir = unique_temp_dir().with_extension("execution-path");
849+
fs::create_dir_all(&dir).unwrap();
850+
let params_path = dir.join("execution.json");
851+
fs::write(
852+
&params_path,
853+
include_str!("../../../docker/configs/dev/asm-execution-params.json"),
854+
)
855+
.unwrap();
856+
let config_path = dir.join("node.toml");
857+
let relative =
858+
load_asm_execution_params(&config_path, Path::new("execution.json")).unwrap();
859+
let absolute = load_asm_execution_params(&config_path, &params_path).unwrap();
860+
assert_eq!(relative, absolute);
861+
assert_eq!(relative.targets()[0].spec_id(), 0);
862+
fs::remove_dir_all(dir).unwrap();
863+
}
864+
865+
#[test]
866+
fn execution_params_reject_missing_or_malformed_file() {
867+
let dir = unique_temp_dir().with_extension("execution-errors");
868+
fs::create_dir_all(&dir).unwrap();
869+
let config_path = dir.join("node.toml");
870+
let params_path = dir.join("execution.json");
871+
let error =
872+
load_asm_execution_params(&config_path, Path::new("execution.json")).unwrap_err();
873+
assert!(
874+
matches!(error, InitError::AsmExecutionParamsRead { path, .. } if path == params_path)
875+
);
876+
fs::write(&params_path, r#"{"genesis_predicate": "AlwaysAccept"}"#).unwrap();
877+
assert!(matches!(
878+
load_asm_execution_params(&config_path, Path::new("execution.json")),
879+
Err(InitError::UnparsableParamsFile(_)),
880+
));
881+
fs::remove_dir_all(dir).unwrap();
882+
}
883+
821884
fn unique_temp_dir() -> PathBuf {
822885
let nanos = SystemTime::now()
823886
.duration_since(UNIX_EPOCH)
@@ -829,6 +892,8 @@ mod tests {
829892
fn fullnode_config() -> Config {
830893
toml::from_str(
831894
r#"
895+
asm_execution = "asm-execution-params.json"
896+
832897
[bitcoind]
833898
rpc_url = "http://localhost:18332"
834899
rpc_user = "alpen"

0 commit comments

Comments
 (0)