Skip to content

Take the cosigner from vtxos/cosigner and the enclave from infra's image; no submodules; call the app vtxos - #60

Merged
aruokhai merged 8 commits into
mainfrom
cosigner-split
Oct 17, 2026
Merged

aruokhai merged 8 commits into
mainfrom
cosigner-split

Conversation

@aruokhai

@aruokhai aruokhai commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

The cosigner moved to vtxos/cosigner, with its history. The crates it shares with this repo (threshold, ark, enclave-client, escrow-service) and the protos went with it. Since v0.1.1 it releases cosigner.wasm built by Nix, and anyone can rebuild a release from its tag and get the same bytes.

The cosigner and the enclave

  • Crates: ffi/ takes ark, threshold and enclave-client as git dependencies at tag = "v0.1.1", as the platform does. ffi/Cargo.lock pins the commit.
  • Protos: make proto takes them from the copy Cargo checked out for ffi/, found with cargo metadata. So one pin covers both the native library and the Dart.
  • The e2e: it runs the dev enclave image infra publishes (the runtime's QEMU enclave plus that cosigner release, in one container), pinned by digest in docker-compose.enclave.yml.
    • The image is built on ubuntu-22.04, so its host tools need glibc 2.34 at most.
    • The harness starts it with docker compose up --wait and passes the suite's settings in GUEST_ENV.
    • Nothing here builds wasm, fetches a bundle or needs wasi-sdk.
    • make enclave-image refuses an image whose cosigner isn't the release ffi/Cargo.toml names.
  • make cosigner: takes cosigner.wasm out of the same image for up-enclave and the MutinyNet deploy. COSIGNER_WASM serves a build of your own instead.
  • scripts/platform.sh: refuses a platform pinned to another cosigner release, rather than patching paths.

No submodules

  • The cosigner submodule is replaced by the git dependencies above.
  • Bob is cli/bin/bob.dart, a small Dart program on the CLI's client (make bob-up, bob-send, bob-down), so the rust-sdk submodule goes too.

Cleanup

  • app-core/ is core/ (package core).
  • Removed: cosigner/, crates/, protocol/protos/, build-cosigner-wasm.sh, wit-drift.sh, enclave-bundle.lock, infrastructure/, HANDOFF.md, e2e/archive, the e2e's own compose file and data directories, and the Makefile targets that built or ran them. The generated .pb.dart files are no longer tracked.
  • The attestation test's four fixtures are copied into core/test/fixtures.

vtxos, not Merlin

  • The app's name on its screens, its notification, its Android and iOS launcher labels, and the passkeys it enrols is vtxos. iOS's label was still the template's "Ap".
  • The README describes what is the wallet's and what is the cosigner's, and links vtxos/runtime, vtxos/infra and ark-core on docs.rs. Before, it linked BitspendPayment/enclave-runtime at an old branch and a vendor/ directory the cosigner no longer has.
  • The enclave's name is vtxos, and MERLIN_ENCLAVE_RUN is VTXOS_ENCLAVE_RUN.
  • Kept: the merlin/frost/* key-derivation labels, which would derive different keys for every existing wallet, the merlin-platform identity label, and the merlin-mutinynet-* bucket.

What was run

  • CI, all four jobs: Rust ffi, Flutter analyze and test, Dart analyze and tests, and the enclave e2e on the runner's KVM against the pinned image.
  • make enclave-image refuses an image labelled with another release (mutation-checked).
  • make bob-up then bob-send against a local stack.

Known flake, pre-existing: a race in heldOnceIndexed

On a busy machine it hits either "three sends Alice to Bob" or "every renewal signs an exit for every VTXO it covers". It fails the same way with main's own cosigner.

The cause is in core/lib/sessions/delegate.dart:

  • An empty VTXO set counts as settled.
  • After a send, the indexer has marked the spent input gone but has not yet listed the change.
  • So the wait returns [] at once, the renewal over the change is skipped, and the delegate and the change's exit are both missing.

It belongs in its own PR.

🤖 Generated with Claude Code

aruokhai and others added 3 commits October 15, 2026 10:01
…fra's image

The cosigner moved out, with the crates it shares with this repository
(threshold, ark, enclave-client, escrow-service) and the protos: it is
vtxos/cosigner now, which builds and releases cosigner.wasm.

- third_party/cosigner is that repository at v0.1.0. The FFI builds over
  its crates, `make proto` generates from its protos, and the local
  platform build patches to them.
- The e2e runs the dev enclave image infra builds (enclave-runtime's
  QEMU enclave and that cosigner release in one container), pinned in
  docker-compose.enclave.yml. The harness starts it with compose and
  passes the suite's settings in GUEST_ENV; nothing here builds wasm,
  fetches a bundle or needs wasi-sdk any more. `make enclave-image`
  refuses an image whose cosigner is not the submodule's release.
- `make cosigner` takes cosigner.wasm out of the same image for what
  boots an enclave of its own: up-enclave and the MutinyNet deploy.
  COSIGNER_WASM serves a build of your own in either.
- The enclave's name is vtxos, and MERLIN_ENCLAVE_RUN is
  VTXOS_ENCLAVE_RUN, as merlin is retired.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The third_party/cosigner submodule went: it was a second checkout to
initialise and keep in step, for three crates and five .proto files.

- ffi/ takes ark, threshold and enclave-client from vtxos/cosigner at
  tag v0.1.1, as MerlinPlatform does; ffi/Cargo.lock pins the commit.
- `make proto` takes the protos from the copy Cargo checked out for
  ffi/, which it finds with cargo metadata. The Dart and the native
  library are built from one pin, and cannot speak two versions of the
  wire.
- `make enclave-image` reads the release from ffi/Cargo.toml.
- scripts/platform.sh stops patching paths, and refuses a platform
  pinned to another cosigner release than ffi/.
- The attestation test's four fixtures are copied into app-core: they
  are a frozen capture, and nothing else needed the crate's tests.

The dev enclave image is v0.1.1's too, packed from runtime bf5f804;
its digest is pinned once infra publishes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cosigner v0.1.1, packed from runtime bf5f804 (PCR0 458969f7...), built and
booted by merlin-infra's dev-enclave-image workflow before it was pushed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aruokhai aruokhai changed the title Take the cosigner from vtxos/cosigner, and the enclave from infra's image Take the cosigner from vtxos/cosigner v0.1.1, and the enclave from infra's image Oct 15, 2026
aruokhai and others added 5 commits October 16, 2026 08:17
Bob, the counterparty the app's integration test pays and is paid by,
was arkade's ark-client-sample from the third_party/rust-sdk submodule
behind a Python proxy: a whole SDK checked out for one dev binary.

He is a CLI wallet now, on the same dev enclave as the app's
(cli/bin/bob.dart), behind the same three endpoints BobClient calls:
/ark-address, /balance, /send. The first start enrols his passkey, runs
DKG and funds him from bitcoind; later ones reopen him. The CLI grows
`create` and `fund` for a named wallet, so Bob never switches the
REPL's active one.

`make bob-down` no longer kills its own shell: `pkill -f` matched the
recipe's command line, which held the pattern.

The wallet has no submodules left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- e2e/archive/: tests and tools for the native cosigner binary, which
  is gone; and the Makefile targets that ran them or that stopped and
  reset it (stress-test, load-test, regtest, runtime-stop, db-reset,
  ark-newaddress), with their variables.
- infrastructure/: the QEMU MutinyNet deployment, which merlin-infra
  replaced, and its mutinynet-deploy target. mutinynet-smoke stays.
- HANDOFF.md: the resume note of a rearchitecture that has landed.
- e2e/docker-compose.yml: an unused, older copy of the root one.
- e2e/hive_db and e2e/bitcoin_data: runtime data committed by mistake.
- protocol/lib/src/generated: three generated files still tracked,
  though `make proto` writes them and .gitignore says so.
- .gitignore entries for directories that no longer exist, and for
  Python, which nothing here is now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The directory and the Dart package both: `package:app_core/` is
`package:core/` in every import, and app, cli and e2e depend on ../core.
Paths in comments, docs and CI follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app's name on its screens, in its notification and launcher labels
(iOS's was still the template's "Ap"), and on the passkeys it enrols.
The README says what is the wallet's and what is the cosigner's instead
of "Merlin", and links vtxos/runtime, vtxos/infra and ark-core on
docs.rs where it linked BitspendPayment/enclave-runtime at an old branch
and a vendor/ directory the cosigner no longer has.

Kept: the merlin-platform identity label and the merlin-mutinynet-*
bucket, which are deployed names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its host tools need glibc 2.34 at most, where the previous image's
passkey-client needed 2.38 and so did not run on a 22.04 host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@aruokhai aruokhai changed the title Take the cosigner from vtxos/cosigner v0.1.1, and the enclave from infra's image Take the cosigner from vtxos/cosigner and the enclave from infra's image; no submodules; call the app vtxos Oct 17, 2026
@aruokhai
aruokhai merged commit 6e5a347 into main Oct 17, 2026
4 checks passed
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