Skip to content

Runtime poc#42

Draft
biryukovmaxim wants to merge 4 commits intokaspanet:feat/zk-convenantsfrom
biryukovmaxim:runtime-poc
Draft

Runtime poc#42
biryukovmaxim wants to merge 4 commits intokaspanet:feat/zk-convenantsfrom
biryukovmaxim:runtime-poc

Conversation

@biryukovmaxim
Copy link
Copy Markdown

No description provided.

Singleton-config runtime program for the risc0 backend. Locks and signers
are abstracted behind generic traits with associated unlocker types; the
ix wire format references signatures by offset so a single sig can unlock
multiple resources. Config uses a zerocopy DST layout (u64 + tag + [u8])
so the body is interpreted per lock variant. Ships with Schnorr/Multisig/
Unlocked locks, Schnorr-sig and prev-tx-V1 witness signers, an Init action
gated by a hardcoded genesis pubkey, 36 unit tests, and an e2e harness
driving the guest ELF directly via risc0_zkvm.
MultisigUnlocker is its own type with its own AuthContext bucket — a
Schnorr-targeted unlocker can no longer satisfy a Multisig lock at the
type level. Multisig contributions land aggregated per resource (one
entry, Vec<[u8;32]>); matchers reject non-strict-asc/duplicate slices
rather than re-sorting. Five signer kinds: SchnorrSigPtr, PrevTxV1Witness,
MultisigSchnorrSigPtr, MultisigPrevTxV1Witness, and the gated ImageProof.
SchnorrSigPtrSigner drops its dead pubkey_idx (Schnorr lock has one key).

PreimageLockView + ImageProofSigner go behind `experimental-image-lock`,
off by default: env::verify only declares an assumption the host attaches,
which is forgeable in our adversarial-host threat model — a real in-guest
verifier (groth16-class) is required and not yet wired.

tx_inputs::parse_output_at_index_v1 now reads spk_len as u64 to match
kaspa's write_var_bytes; the e2e harness uses kaspa-consensus-core's
public transaction_v1_rest_preimage to build the prev-tx fixture instead
of hand-rolling bytes.
…sing

After the id-sort merge, the runtime sees resources in lexicographic id
order rather than transaction-declaration order, so apply handlers can
no longer assume "the config sits at index 0." Each action body now
carries a u8 updater_idx pointing at its target resource;
apply_update/apply_init look up resources[updater_idx] instead of the
hardcoded TARGET_IDX=0. Same shape as Solana's
CompiledInstruction.account_indices.

decode_ix takes n_resources and rejects updater_idx >= n_resources at
decode time so dispatch can stay unconditional — matches the "no
post-sort fixups" posture already in place for signers' resource_idx
ordering.

Tests: four ix.rs unit tests covering each idx in a 3-resource set,
multiple actions targeting different resources, mid-stream rejection on
a bad idx, and order-agnostic action sequences. Two new e2e tests place
config_resource_id() at lex position 1 (decoy [0u8;32] precedes it) and
verify both the happy path (updater_idx=1 succeeds) and that
updater_idx=0 is rejected because the decoy is not the config.

Drive-by lints: dead drop(cur) on a non-Drop ConfigView, two needless
'a/'b lifetimes, a useless [u8;32]->[u8;32] .into() in the test signer,
and a doc list that needed a blank line. rustfmt drift in surrounding
files folded in.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant