Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c44c76d
feat(common): add fork schedule primitives
prajwolrg Jul 6, 2026
fb177ab
feat(params)!: split AsmParams into genesis and STF sections
prajwolrg Jul 7, 2026
d09a20c
refactor!: reduce AsmSpec to a type-level pipeline declaration
prajwolrg Jul 7, 2026
8924b59
refactor(spec): derive genesis sections from the spec's subprotocol list
prajwolrg Jul 7, 2026
f51831d
refactor(common)!: bundle subprotocol hook inputs into per-phase ctx …
prajwolrg Jul 7, 2026
32bd1d3
feat!: thread StfParams from every executor to the subprotocol hooks
prajwolrg Jul 7, 2026
fc2f60f
feat(bridge): gate unstake txs on the first fork
prajwolrg Jul 7, 2026
dd153a4
feat(storage): add sled-backed fork-activation store
prajwolrg Jul 7, 2026
3f45cca
feat(worker): add fork-activation persistence as a context concern
prajwolrg Jul 7, 2026
0d47a97
feat(admin): carry the activating fork in the ASM STF VK update
prajwolrg Jul 8, 2026
a7ef2f2
feat(worker): discover fork activations from ASM VK upgrade logs
prajwolrg Jul 6, 2026
d867438
test: cover the unstake fork gate and upgrade lifecycle
prajwolrg Jul 6, 2026
558aba5
fix(worker): reject unsupported fork activation blocks
prajwolrg Jul 8, 2026
aaabec4
refactor(worker): split fork discovery from activation persistence
prajwolrg Jul 8, 2026
2538ba5
fix(worker): reject upgrades naming already-active forks
prajwolrg Jul 8, 2026
7f725b9
feat(prover): switch ASM proving artifacts across VK upgrades
prajwolrg Jul 6, 2026
befa081
feat(guest): add pre-unstake ASM guest for upgrade tests
prajwolrg Jul 6, 2026
d5b12a3
feat(txgen): add asm-txgen test-support CLI
prajwolrg Jul 6, 2026
dcb0c3c
test(functional): drive the full ASM fork upgrade end to end
prajwolrg Jul 6, 2026
89d7170
ci: build asm-txgen for the functional test job
prajwolrg Jul 6, 2026
099659e
test(functional): annotate params_kwargs so ty accepts the splat
prajwolrg Jul 6, 2026
c67a9de
feat(dbtool): expose the fork-activation store
prajwolrg Jul 6, 2026
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
6 changes: 3 additions & 3 deletions .github/workflows/functional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ jobs:
- name: Build with coverage instrumentation
run: |
COV_TARGET_DIR="$GITHUB_WORKSPACE/target/llvm-cov-target"
# dbtool is exercised by the dbtool functional tests; build it into the
# same target dir so it lands on PATH alongside the runner.
RUSTFLAGS="-Cinstrument-coverage" cargo build --locked --bin strata-asm-runner --bin dbtool --target-dir "$COV_TARGET_DIR"
# dbtool and asm-txgen are exercised by the functional tests; build them
# into the same target dir so they land on PATH alongside the runner.
RUSTFLAGS="-Cinstrument-coverage" cargo build --locked --bin strata-asm-runner --bin dbtool --bin asm-txgen --target-dir "$COV_TARGET_DIR"

- name: Run functional tests
id: funcTestsRun
Expand Down
31 changes: 31 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 @@ -42,6 +42,7 @@ members = [

# binaries listed separately
"bin/asm-runner",
"bin/asm-txgen",
"bin/dbtool",
"bin/prover-perf",
"guest-builder/sp1",
Expand Down
23 changes: 14 additions & 9 deletions bin/asm-runner/src/bootstrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) async fn bootstrap(
aux_db,
manifest_db,
mmr_db,
fork_activation_db,
export_entries_db,
} = create_storage(&config.database)?;

Expand Down Expand Up @@ -65,6 +66,7 @@ pub(crate) async fn bootstrap(
aux_db.clone(),
manifest_db.clone(),
mmr_db.clone(),
fork_activation_db,
);

// 5. Launch ASM worker.
Expand All @@ -74,16 +76,16 @@ pub(crate) async fn bootstrap(
// on a runtime worker thread here, so wrap the build in `block_in_place` to allow blocking;
// the worker's own loop runs on a dedicated sync thread where blocking is already fine.
let asm_worker = task::block_in_place(|| {
AsmWorkerBuilder::new()
AsmWorkerBuilder::<_, StrataAsmSpec>::new()
.with_context(worker_context)
.with_asm_spec(StrataAsmSpec)
.with_params(params.clone())
.with_params(params)
.launch(&executor)
})?;

let asm_worker = Arc::new(asm_worker);

// 6. Finish orchestrator wiring if it was configured.
let genesis_block = asm_worker.genesis_block();
let proof_rpc_deps = if let Some((orch_config, proof_db, moho_state_db, backend)) = orch_prep {
let rpc_deps = AsmProofRpcDeps {
proof_db: proof_db.clone(),
Expand All @@ -92,12 +94,15 @@ pub(crate) async fn bootstrap(
};

let ProofBackend {
asm_host,
asm_hosts,
moho_host,
asm_predicate,
moho_predicate,
} = backend;

// The genesis Moho state advertises the predicate of the artifact
// active at genesis — by convention the first configured ASM entry.
let genesis_asm_predicate = asm_hosts[0].0.clone();

// Spin the Moho worker off onto its own service task, driven by the ASM
// worker's per-block commit stream. It derives each block's MohoState
// (and the export-entry leaves its ExportState MMR commits to) from the
Expand All @@ -118,8 +123,8 @@ pub(crate) async fn bootstrap(
let moho_worker = MohoWorkerBuilder::new()
.with_context(moho_context)
.with_subscription(asm_worker.subscribe_blocks())
.with_genesis_block(params.anchor.block)
.with_asm_predicate(asm_predicate.clone())
.with_genesis_block(genesis_block)
.with_asm_predicate(genesis_asm_predicate)
.launch(&executor)
.await?;

Expand All @@ -133,7 +138,7 @@ pub(crate) async fn bootstrap(
aux_db.clone(),
bitcoin_client.clone(),
);
let input_builder = InputBuilder::new(params.anchor.block, asm_predicate, moho_predicate);
let input_builder = InputBuilder::new(genesis_block, moho_predicate);

// Drive the prover from the *Moho* worker's commit stream, not the ASM
// worker's: the Moho worker emits a block only after it has persisted
Expand All @@ -155,7 +160,7 @@ pub(crate) async fn bootstrap(
// `LocalSet` needed.
let _prover_handle = ProverWorkerBuilder::new()
.with_context(prover_ctx)
.with_hosts(asm_host, moho_host)
.with_hosts(asm_hosts, moho_host)
.with_config(orch_config)
.with_input_builder(input_builder)
.with_block_subscription(block_subscription)
Expand Down
11 changes: 11 additions & 0 deletions bin/asm-runner/src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ impl AsmStateApiServer for AsmRpcServer {
}
}

async fn get_operators(&self, block_hash: BlockHash) -> RpcResult<Vec<u32>> {
match self.get_bridge_state(block_hash).await? {
Some(bridge_state) => Ok(bridge_state
.operators()
.current_multisig()
.active_indices()
.collect()),
None => Ok(vec![]),
}
}

async fn get_checkpoint_tip(&self, block_hash: BlockHash) -> RpcResult<Option<CheckpointTip>> {
match self.get_checkpoint_state(block_hash).await? {
Some(checkpoint_state) => Ok(Some(*checkpoint_state.verified_tip())),
Expand Down
6 changes: 5 additions & 1 deletion bin/asm-runner/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
use std::sync::Arc;

use anyhow::Result;
use asm_storage::{SledAsmAuxDataDb, SledAsmManifestDb, SledAsmManifestMmrDb, SledAsmStateDb};
use asm_storage::{
SledAsmAuxDataDb, SledAsmManifestDb, SledAsmManifestMmrDb, SledAsmStateDb, SledForkActivationDb,
};
use strata_asm_moho_storage::SledExportEntriesDb;

use crate::config::DatabaseConfig;
Expand All @@ -14,6 +16,7 @@ pub(crate) struct Storage {
pub aux_db: Arc<SledAsmAuxDataDb>,
pub manifest_db: Arc<SledAsmManifestDb>,
pub mmr_db: Arc<SledAsmManifestMmrDb>,
pub fork_activation_db: Arc<SledForkActivationDb>,
pub export_entries_db: SledExportEntriesDb,
}

Expand All @@ -25,6 +28,7 @@ pub(crate) fn create_storage(config: &DatabaseConfig) -> Result<Storage> {
aux_db: Arc::new(SledAsmAuxDataDb::open(&db)?),
manifest_db: Arc::new(SledAsmManifestDb::open(&db)?),
mmr_db: Arc::new(SledAsmManifestMmrDb::open(&db)?),
fork_activation_db: Arc::new(SledForkActivationDb::open(&db)?),
export_entries_db: SledExportEntriesDb::open(&db)?,
})
}
36 changes: 33 additions & 3 deletions bin/asm-runner/src/worker_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@

use std::sync::Arc;

use asm_storage::{SledAsmAuxDataDb, SledAsmManifestDb, SledAsmManifestMmrDb, SledAsmStateDb};
use asm_storage::{
SledAsmAuxDataDb, SledAsmManifestDb, SledAsmManifestMmrDb, SledAsmStateDb, SledForkActivationDb,
};
use bitcoin::{Block, BlockHash, Network, block::Header};
use bitcoind_async_client::{Client, error::ClientError, traits::Reader};
use strata_asm_common::{AnchorState, AsmManifest, AsmManifestHash, AuxData};
use strata_asm_common::{AnchorState, AsmManifest, AsmManifestHash, AuxData, ForkActivation};
use strata_asm_worker::{
AnchorStateStore, AuxDataStore, L1DataProvider, ManifestMmrStore, WorkerError, WorkerResult,
AnchorStateStore, AuxDataStore, ForkActivationStore, L1DataProvider, ManifestMmrStore,
WorkerError, WorkerResult,
};
use strata_btc_types::{BitcoinTxid, L1BlockIdBitcoinExt, RawBitcoinTx};
use strata_identifiers::{L1BlockCommitment, L1BlockId};
Expand All @@ -36,9 +39,14 @@ pub(crate) struct AsmWorkerContext {
aux_db: Arc<SledAsmAuxDataDb>,
manifest_db: Arc<SledAsmManifestDb>,
mmr_db: Arc<SledAsmManifestMmrDb>,
fork_activation_db: Arc<SledForkActivationDb>,
}

impl AsmWorkerContext {
#[expect(
clippy::too_many_arguments,
reason = "one argument per storage concern"
)]
pub(crate) fn new(
runtime_handle: Handle,
bitcoin_client: Arc<Client>,
Expand All @@ -47,6 +55,7 @@ impl AsmWorkerContext {
aux_db: Arc<SledAsmAuxDataDb>,
manifest_db: Arc<SledAsmManifestDb>,
mmr_db: Arc<SledAsmManifestMmrDb>,
fork_activation_db: Arc<SledForkActivationDb>,
) -> Self {
Self {
runtime_handle,
Expand All @@ -57,6 +66,7 @@ impl AsmWorkerContext {
aux_db,
manifest_db,
mmr_db,
fork_activation_db,
}
}
}
Expand Down Expand Up @@ -233,6 +243,26 @@ impl ManifestMmrStore for AsmWorkerContext {
}
}

impl ForkActivationStore for AsmWorkerContext {
fn record_fork_activation(&self, activation: ForkActivation) -> WorkerResult<()> {
self.fork_activation_db
.put(activation)
.map_err(|_| WorkerError::DbError)
}

fn list_fork_activations(&self) -> WorkerResult<Vec<ForkActivation>> {
self.fork_activation_db
.list()
.map_err(|_| WorkerError::DbError)
}

fn prune_fork_activations_after(&self, after_height: u32) -> WorkerResult<()> {
self.fork_activation_db
.prune_after(after_height)
.map_err(|_| WorkerError::DbError)
}
}

impl AuxDataStore for AsmWorkerContext {
fn store_aux_data(&self, blockid: &L1BlockCommitment, data: &AuxData) -> WorkerResult<()> {
self.aux_db
Expand Down
27 changes: 27 additions & 0 deletions bin/asm-txgen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "asm-txgen"
version = "0.1.0"
edition = "2024"

[lints]
workspace = true

[dependencies]
strata-asm-proto-admin-txs = { workspace = true, features = ["test-utils"] }
strata-asm-proto-bridge-v1-txs.workspace = true
strata-crypto.workspace = true
strata-l1-envelope-fmt.workspace = true
strata-l1-txfmt.workspace = true
strata-predicate = { workspace = true, features = ["serde"] }
strata-test-utils-btcio.workspace = true

anyhow.workspace = true
bitcoin.workspace = true
bitcoind-async-client.workspace = true
clap.workspace = true
hex.workspace = true
k256.workspace = true
rand.workspace = true
serde_json.workspace = true
ssz.workspace = true
tokio.workspace = true
Loading
Loading