BREAKING CHANGE: GenesisAction::DeployProgram and IndexerConfig.deploy_programs are removed. The cross-zone programs (inbox, outbox, ping_sender, ping_receiver, bridge_lock, wrapped_token) are now base builtins in testnet_initial_state, because program bytecode exceeds the genesis block inscription limit, so they cannot be shipped through genesis transactions.
verify_block populated the seen-set before accept_block, so a dispatch verified in a block that then parked poisoned seen without the inbox ever recording the key on chain, letting a later forged dispatch reuse the key to skip re-derivation. verify_block now returns the verified keys and the ingest loop records them via record_seen only on AcceptOutcome::Applied, so seen mirrors the inbox's on-chain seen-shard.
Cross-zone builtin programs are no longer registered in the production
genesis. A zone that participates declares the ones it uses via a new
GenesisAction::DeployProgram (sequencer) and a matching deploy_programs
list (indexer), both resolved through CrossZoneProgram and registered
with with_programs. Cross-zone genesis accounts (inbox config,
wrapped-token config) are seeded through the state constructor for a
receiving zone, and bridge-lock holdings are seeded from their actions
regardless of receiving config, dropping V03State::insert_genesis_account.
GenesisAction amounts now use the Balance alias. Documents cross_zone as
the reference LEZ adapter and the bridge demo as not production-safe.
The sequencer's DeployProgram set and the indexer's deploy_programs are
configured separately, so both nodes now log a deterministic genesis
fingerprint (V03State::genesis_fingerprint) at startup: equal values
confirm the two genesis states agree, a mismatch flags a divergent
deploy set.
BREAKING CHANGE: the genesis state root changes (cross-zone builtins are
out of production genesis) and the sequencer/indexer configs gain the
DeployProgram / deploy_programs list that cross-zone-participating zones
must set.
BREAKING:
Before: An endpoint exposing getting a single proof for a commitment
existed.
After: There is one endpoint where you give a vector of commitments
and a vector of Maybe proofs back alongside the shared root.
Mitigation: Use the new rpc endpoint with the appopriate vector.
The Option B verifier returned Err on a cross-zone dispatch whose message key
was already in its seen set, and that halts indexer ingestion. A legitimate
re-delivery, for example after a sequencer restart re-injects, could then
permanently stall an honest indexer. The inbox already treats a re-delivered
message as an idempotent no-op on chain, so the verifier now continues past an
already-seen key instead of bailing. Forgery detection on first-seen dispatches
is unchanged.
Also notes that one pinned block-signing key per peer is sufficient until
decentralized sequencing, and strengthens the replay test so it only passes via
the seen-key short-circuit.
Remove the stale top-level programs/ core crates (bridge_lock_core,
cross_zone_inbox_core, cross_zone_outbox_core, ping_core, wrapped_token_core),
leftover copies from the initial cross-zone port before programs moved to the
per-program-crate layout. The live cores under lez/programs/*/core keep the
same package names and remain the ones actually used.