Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 3 additions & 6 deletions .github/workflows/cosigner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1

- name: Install cargo-component
run: cargo install cargo-component
targets: wasm32-wasip2

- name: Cache cargo registry & build
uses: actions/cache@v4
Expand All @@ -38,13 +35,13 @@ jobs:
key: cosigner-${{ hashFiles('cosigner/Cargo.lock', 'crates/threshold/Cargo.toml', 'crates/ark/Cargo.toml') }}

- name: Build cosigner WASM
run: cd cosigner && cargo component build --release
run: cd cosigner && cargo build --release --target wasm32-wasip2

- name: Upload WASM artifact
uses: actions/upload-artifact@v4
with:
name: cosigner-wasm
path: cosigner/target/wasm32-wasip1/release/cosigner.wasm
path: cosigner/target/wasm32-wasip2/release/cosigner.wasm
retention-days: 90

release:
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,11 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1
targets: wasm32-wasip2

- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler

- name: Install cargo-component
run: cargo install cargo-component

- name: Cache cargo
uses: actions/cache@v4
with:
Expand All @@ -43,7 +40,7 @@ jobs:
- name: Build all
run: |
cargo build --release --manifest-path ffi/Cargo.toml
(cd cosigner && cargo component build --release)
(cd cosigner && cargo build --release --target wasm32-wasip2)
cargo build --release --manifest-path cosigner-runtime/Cargo.toml
cargo build --release --manifest-path e2e/signer-server/Cargo.toml

Expand All @@ -54,7 +51,7 @@ jobs:
retention-days: 1
path: |
ffi/target/release/libmpcwallet_ffi.so
cosigner/target/wasm32-wasip1/release/cosigner.wasm
cosigner/target/wasm32-wasip2/release/cosigner.wasm
cosigner-runtime/target/release/cosigner-runtime
e2e/signer-server/target/release/signer-server

Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/flutter-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,11 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1,x86_64-linux-android
targets: wasm32-wasip2,x86_64-linux-android

- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler

- name: Install cargo-component
run: cargo install cargo-component

- name: Cache cargo
uses: actions/cache@v4
with:
Expand Down Expand Up @@ -75,7 +72,7 @@ jobs:
- name: Build MPCWallet host binaries
run: |
cargo build --release --manifest-path cosigner-runtime/Cargo.toml
(cd cosigner && cargo component build --release)
(cd cosigner && cargo build --release --target wasm32-wasip2)
cargo build --release --manifest-path e2e/signer-server/Cargo.toml

- name: Build FFI for Android x86_64
Expand Down Expand Up @@ -124,7 +121,7 @@ jobs:
ASP_URL: http://127.0.0.1:7070
run: |
nohup cosigner-runtime/target/release/cosigner-runtime \
--wasm cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074 > /tmp/cosigner-runtime.log 2>&1 &
sleep 3
curl -sS http://127.0.0.1:7074/health || curl -sS http://127.0.0.1:7074/ || true
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"rust-analyzer.linkedProjects": [
"cosigner/Cargo.toml",
"cosigner-runtime/Cargo.toml",
"crates/threshold/Cargo.toml",
"crates/ark/Cargo.toml",
Expand Down
18 changes: 9 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ software: regtest-up bitcoin-init adb-reverse cosigner-build runtime-build ffi-b
export ELECTRUM_URL=127.0.0.1 ELECTRUM_PORT=50001 \
BITCOIN_RPC_USER=admin1 BITCOIN_RPC_PASSWORD=123; \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074'

# 3b) Start regtest + arkd for SOFTWARE signer (no USB device required) — Ark enabled
Expand Down Expand Up @@ -144,7 +144,7 @@ software-ark: cosigner-build runtime-build ffi-build ffi-android
ASP_URL=http://127.0.0.1:7070 \
FCM_SERVICE_ACCOUNT_JSON="$$(cat $${FCM_SA_FILE:-$$HOME/Downloads/vtxos-key.json} 2>/dev/null)"; \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074'

# 4) Start regtest for hardware device (no Ark) — server runs in foreground
Expand All @@ -161,7 +161,7 @@ hardware: regtest-up bitcoin-init adb-reverse cosigner-build runtime-build ffi-b
export ELECTRUM_URL=127.0.0.1 ELECTRUM_PORT=50001 \
BITCOIN_RPC_USER=admin1 BITCOIN_RPC_PASSWORD=123; \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074'

# 5) Start regtest for hardware device with Ark — server runs in foreground
Expand Down Expand Up @@ -189,7 +189,7 @@ hardware-ark: cosigner-build runtime-build ffi-build ffi-android
BITCOIN_RPC_USER=admin1 BITCOIN_RPC_PASSWORD=123 \
ASP_URL=http://127.0.0.1:7070; \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074'

# 5) Stop everything (server, signer, mine loop, Docker)
Expand Down Expand Up @@ -337,8 +337,8 @@ threshold-ffi-test: ffi-test
# Server & cosigner
cosigner-build:
@echo "Building cosigner WASM component..."
cd cosigner && cargo component build --release
@echo "Built: cosigner/target/wasm32-wasip1/release/cosigner.wasm"
cd cosigner && cargo build --release --target wasm32-wasip2
@echo "Built: cosigner/target/wasm32-wasip2/release/cosigner.wasm"

runtime-build:
@echo "Building server..."
Expand Down Expand Up @@ -391,7 +391,7 @@ runtime-run: cosigner-build runtime-build
export BITCOIN_RPC_USER=admin1 && \
export BITCOIN_RPC_PASSWORD=123 && \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074 &
@sleep 2
@echo "MPC Wallet Server running in background."
Expand Down Expand Up @@ -485,7 +485,7 @@ signet-hardware-ark: cosigner-build runtime-build ffi-build ffi-android
export BITCOIN_NETWORK=signet && \
export ASP_URL=$(MUTINYNET_ASP_URL) && \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074

signet-down:
Expand Down Expand Up @@ -538,7 +538,7 @@ integration-test-ci-ark: runtime-stop signer-stop arkd-up bitcoin-init arkd-init
BITCOIN_RPC_USER=admin1 BITCOIN_RPC_PASSWORD=123 \
ASP_URL=http://127.0.0.1:7070 && \
cd cosigner-runtime && cargo run --release --bin cosigner-runtime -- \
--wasm ../cosigner/target/wasm32-wasip1/release/cosigner.wasm \
--wasm ../cosigner/target/wasm32-wasip2/release/cosigner.wasm \
--port 7074 &
@sleep 5
cd app && flutter pub get && \
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Handlers run inside `spawn_blocking` so CPU-bound WASM work (FROST round1, DKG p

### Inner layer: WASM sandbox per user

Threshold cryptography (FROST, DKG, Schnorr verify, Taproot tweaking) lives entirely inside [`cosigner/`](cosigner/), a WASI Component Model crate compiled to `wasm32-wasip1`. The Rust runtime never sees raw secret shares — only opaque session handles into the WASM linear memory.
Threshold cryptography (FROST, DKG, Schnorr verify, Taproot tweaking) lives entirely inside [`cosigner/`](cosigner/), a WASI Component Model crate compiled to `wasm32-wasip2`. The Rust runtime never sees raw secret shares — only opaque session handles into the WASM linear memory.

Each user actor instantiates the cosigner component into a fresh `wasmtime::Store`:

Expand Down Expand Up @@ -200,7 +200,7 @@ High-level Dart API that orchestrates the full MPC protocol: drives DKG, signing

### Threshold library ([crates/threshold/](crates/threshold/))

`#![no_std]` Rust implementation of FROST over secp256k1. Includes the full 3-round DKG, Pedersen VSS, nonce commitments, signature share computation, Lagrange interpolation, Taproot key tweaking, and key refresh. Compiles for four targets: native Rust, `wasm32-wasip1` (cosigner WASM), `thumbv8m.main-none-eabihf` (HW signer Secure world), and Dart FFI.
`#![no_std]` Rust implementation of FROST over secp256k1. Includes the full 3-round DKG, Pedersen VSS, nonce commitments, signature share computation, Lagrange interpolation, Taproot key tweaking, and key refresh. Compiles for four targets: native Rust, `wasm32-wasip2` (cosigner WASM), `thumbv8m.main-none-eabihf` (HW signer Secure world), and Dart FFI.

## Build & Run

Expand All @@ -215,12 +215,11 @@ High-level Dart API that orchestrates the full MPC protocol: drives DKG, signing

```bash
# Rust targets the runtime + cosigner need
rustup target add wasm32-wasip1 # cosigner WASM
rustup target add wasm32-wasip2 # cosigner WASM
rustup target add aarch64-linux-android # FFI for Android arm64
rustup target add thumbv8m.main-none-eabihf # HW signer (only if needed)
rustup toolchain install nightly # TrustZone CMSE features (HW signer only)

cargo install cargo-component # WASI component building
cargo install probe-rs-tools # only for HW signer flashing
```

Expand Down
2 changes: 1 addition & 1 deletion cosigner-runtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl ServerConfig {
.unwrap_or_else(|_| "http://127.0.0.1:8080".to_string()),
enclave_mgmt_token: env::var("ENCLAVE_RUNTIME_TOKEN").unwrap_or_default(),
cosigner_wasm_path: env::var("COSIGNER_WASM_PATH").unwrap_or_else(|_| {
"../cosigner/target/wasm32-wasip1/release/cosigner.wasm".to_string()
"../cosigner/target/wasm32-wasip2/release/cosigner.wasm".to_string()
}),
auto_settle_safety_margin_secs: env::var("AUTO_SETTLE_SAFETY_MARGIN_SECS")
.ok()
Expand Down
2 changes: 1 addition & 1 deletion cosigner-runtime/tests/isolation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn wasm_path() -> PathBuf {
manifest_dir
.parent()
.unwrap()
.join("cosigner/target/wasm32-wasip1/release/cosigner.wasm")
.join("cosigner/target/wasm32-wasip2/release/cosigner.wasm")
}

fn create_instance(
Expand Down
5 changes: 5 additions & 0 deletions cosigner/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# The cosigner is a WASI Component Model crate. Building for wasm32-wasip2 lets
# rustc emit the component directly via wasm-component-ld — no `cargo component`
# step. Setting the target here also drives rust-analyzer's analysis of this crate.
[build]
target = "wasm32-wasip2"
1 change: 0 additions & 1 deletion cosigner/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 0 additions & 7 deletions cosigner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ crate-type = ["cdylib"]
threshold = { path = "../crates/threshold", features = ["std"] }
ark = { path = "../crates/ark", features = ["std"] }
wit-bindgen = "0.41"
wit-bindgen-rt = "0.41"
serde_json = "1"
rand = "0.8"
k256 = { version = "0.13", features = ["arithmetic"] }

[package.metadata.component]
package = "component:threshold"

[package.metadata.component.target]
world = "threshold-world"
2 changes: 1 addition & 1 deletion cosigner/src/ark_ops.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Ark protocol WASM operations.

use crate::bindings::exports::component::threshold::types::ThresholdError;
use crate::exports::component::threshold::types::ThresholdError;
use crate::convert;

pub fn ark_default_vtxo_script_pubkey(
Expand Down
2 changes: 1 addition & 1 deletion cosigner/src/auth_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use threshold::auth;

use crate::bindings::exports::component::threshold::types::ThresholdError;
use crate::exports::component::threshold::types::ThresholdError;
use crate::convert;

pub fn verify_schnorr_signature(
Expand Down
Loading
Loading