Skip to Content

MPC Signing

This page explains how The Vault produces a cryptographic signature using threshold MPC, and describes the roles of the coordinator, server signers, and the mobile signer during a signing session.

Overview

The Vault uses threshold ECDSA (secp256k1) for all supported chains — Ethereum, TRON, and Bitcoin (P2WPKH SegWit) — implemented with an audited, production-grade threshold cryptography library. The protocol is designed so that:

  • No individual signer ever computes or holds the complete private key.
  • The produced signature is indistinguishable from a standard ECDSA signature on-chain.
  • The protocol is secure under concurrent session assumptions (multiple wallets can sign simultaneously without interference).

Coordinator Role

The MPC Coordinator is a stateless orchestration service. It does not hold a key share. Its responsibilities are:

  1. Receive a signing request from the wallet API.
  2. Open a signing session with a unique sessionId.
  3. Send the transaction payload and sessionId to each required signer.
  4. Collect partial signature responses.
  5. Combine partial signatures using the MPC protocol’s combiner function.
  6. Return the assembled transaction to the wallet API.

The coordinator is designed as a stateless, horizontally scalable service.

Server Signer Role

The two server signers are always-online services, each storing one key share encrypted at rest. When a signing request arrives:

  1. The signer decrypts its key share.
  2. It uses the key share to compute its partial signature over the transaction hash.
  3. The partial signature is returned to the coordinator over a secure channel.
  4. The key share is re-encrypted and the in-memory copy is zeroed.

Sessions for the same wallet are serialised to prevent double-signing. Cross-wallet sessions run in parallel.

Mobile Signer Role

The mobile signer’s key share is stored encrypted at rest in the device’s secure storage. The signing flow in the mobile app:

  1. A push notification arrives: “Signing request for Treasury - Operating: Send 10,000 USDC to 0xRecipient…”
  2. The user opens the app. The transaction details are displayed, fetched from the Vault API over HTTPS/mTLS.
  3. The user reviews the destination, amount, asset, and network.
  4. The user authenticates with their app PIN. The secure hardware releases the key share for use.
  5. The app decrypts its key share into memory and computes its partial signature locally, in its own process.
  6. The partial signature is sent to the coordinator.
  7. The app displays a confirmation: “Signed. Transaction is being broadcast.”

The key share is stored encrypted at rest and is decrypted into app memory only for the moment the partial signature is computed, then wiped. It never leaves the device — only the partial signature is transmitted — but the computation runs in the app process, not inside a Secure Enclave / StrongBox.

Signing Session State Machine

Replay Protection

Each signing session includes:

  • A unique sessionId (UUID v4)
  • The transaction’s nonce (Ethereum) or specific UTXO set (Bitcoin)
  • A session timestamp and expiry

Signers reject requests with a sessionId they have already processed, and they verify the session has not expired. This prevents replay attacks where a captured partial signature could be reused.

Concurrent Signing

The Vault supports concurrent signing sessions across different wallets. Sessions for the same wallet are serialised to prevent nonce reuse on EVM chains.

Audit Trail

Every signing event is logged:

{ "event": "mpc.signing.complete", "sessionId": "sess_01A2B3C4D5E6F7G8", "walletId": "wal_01J2K3L4M5N6P7Q8", "transactionId": "txn_01K3L4M5N6P7Q8R9", "signers": ["server-signer-1", "server-signer-2", "mobile:dev_01X2Y3Z4"], "durationMs": 2340, "timestamp": "2026-03-11T11:05:23Z" }