MPC wallet architecture

Crypto custody & compliance · engineering reference

MPC wallet architecture

MPC stands for multi-party computation. An MPC wallet splits a private key into shares held by different parties, and those parties compute a signature together without ever reassembling the key on any one machine. Nobody holds a spendable key, so nobody can be robbed of one. This sheet covers the protocols that do it, where to put the shares, what refresh and resharing actually change, and the attacks a threshold does nothing about.

VOLATILE CLAIMS: DATE-TAGGEDPRINT: LANDSCAPE TABLES

Start here if this is new

A normal wallet has one private key, and whoever holds it can move the money. An MPC wallet never creates that key. Each participating machine generates a share, and signing is a short conversation between enough of those machines to meet a threshold. The chain receives one ordinary signature and cannot tell the difference.

How is this different from multisig?

Multisig puts several real keys on chain and the chain enforces the rule, so anyone can see which keys approved. MPC does the same job off chain and hands the chain a single ordinary signature. That is why MPC works on chains with no multisig support, and also why the chain records nothing about who signed.

If nobody holds a key, what can still go wrong?

Threshold signing protects the key material, not the decision to sign. An attacker who takes over the system that requests signatures gets a valid signature from a perfectly healthy quorum. Every share behaved correctly, and the money is still gone.

Why does share refresh keep coming up?

Refresh re-randomizes every share while the address stays the same, which makes all older shares useless. The realistic attack is not compromising three machines in one night, it is compromising one this quarter and another next year. Refresh puts a deadline on that.

How do you back up a key that does not exist?

Carefully, because this is where the scheme quietly collapses back into single-key custody. If you can bring enough shares together in one place to restore, you have rebuilt the single key you were trying to avoid.

If you remember one lineMPC protects the key. It does not protect the decision to sign. Spend your review time on the policy engine.

What the threshold buys you, and where it stops

One worked 2-of-3 wallet: three shares exist, any two of them can sign, and one on its own is useless. Every value here is explained in the sections below.

Quorum2 of 3shares, no dealer
Key originDKGkey never assembled
Below threshold0 bitsfewer than t reveal nothing
RefreshEpochsame address, new shares
ReshareIdenticalpublic key, byte-for-byte
BoundaryPolicykey use protected, not intent

Threshold signing model

The proofs describe an ideal protocol. NIST IR 8214 is blunt about how far shipped code can drift from it. Treat the signer, the policy engine, the callback service, the approver device, and the audit store as five separate places an attacker can land, and test each one.

TermPrecise meaningProduction test
ShareA secret contribution; never a standalone private keyExfiltrating one share cannot sign or reconstruct below threshold
DKGParties jointly create the key; no dealer knows itTranscript and independently derived public key agree
t-of-nAny t participants can sign; fewer reveal nothingExercise every authorized quorum and one below-threshold set
RefreshNew shares, same aggregate key and addressOld epoch + new epoch shares do not form a valid quorum
ReshareChange participants or quorum without moving fundsPublic key is byte-identical before and after
BoundaryMPC protects key use, not transaction intentPOLICY IS SEPARATE

What a 2-of-3 actually promises

The math counts shares. Your risk depends on what those shares have in common. Three VMs in one cloud account share an IAM role, a hypervisor, an update channel, and an admin, so that wallet is really 1-of-1 wearing a 2-of-3 label.

Two-of-three threshold signing across three trust domains Three separate trust domains each hold one share. Any two shares together produce a valid signature; a single share on its own yields nothing. A refresh rotates all three shares while the public key and address stay the same. Cloud HSM · account A Operator device Recovery co-signer s1s2s3 quorum met → one ordinary signature alone → 0 bits Refresh rotates s1 s2 s3 · public key and address unchanged Independent IAM · hypervisor · update channel · operator · region · recovery authority
The chain records one ordinary signature and says nothing about which two domains produced it. If you want to know who signed, you have to log it yourself.

Protocol lineage

Two vendors can both say “GG18” and ship very different code. The GG-family (GG18 → GG20 → CMP → CGGMP) is one lineage built on Paillier homomorphic encryption; DKLs (DKLs18 → DKLS23) is a separate lineage built on oblivious transfer — they don’t share a trust base, so “which generation” and “which family” are different diligence questions. Get the paper revision, the implementation commit, the curve suite, and the audit that actually covered that commit. RFC 9591 was checked August 2026.

FamilyOutput / quorumRounds & preprocessingCore assumptionOperational reading
Lindell17ECDSA · 2-partyInteractive online signingPaillier + ZK proofsHistorical baseline; use only audited, patched implementations
GG18ECDSA · t-of-nOffline presigning + online roundsPaillier MtADealerless DKG, arbitrary thresholds; heavy interaction, implementation proof validation is security-critical
GG20ECDSA · t-of-nAdds identifiable abortPaillier MtAFixes silent denial-of-service by abort; blame does not remove malformed-proof risk
CMPECDSA · t-of-nHeavy offline preprocessing; ~1 online roundPaillier + adaptive-adversary proofPresignatures ready before the transaction exists; that presignature inventory itself becomes security-sensitive state
CGGMPECDSA · t-of-n3 preprocessing rounds + 1 online round; identifiable abortPaillier + commitments; UC-secureModern production baseline; pin paper, code commit, and audit together
DKLs18ECDSA · 2-party2 messages; no Paillier preprocessingOblivious transferFast, minimal 2-party case; superseded by DKLS23 for anything beyond two parties
DKLS23ECDSA · t-of-n3 rounds, general thresholdOblivious transferAvoids Paillier/RSA-style assumptions entirely; different implementation and side-channel surface than the GG family
FROST (RFC 9591)Schnorr / EdDSA · t-of-n2 signing roundsPrime-order group + hashRFC is Informational; coordinator selection remains external
MuSig2 (BIP 327)Schnorr · n-of-n2 communication roundsKey aggregationNot threshold: every signer is required

The key's lifecycle in one picture

Not the wallet app's lifecycle — the underlying key material's: how the shares behind one address are created, used, rotated, and eventually destroyed. Two of these five operations keep the address you already gave your counterparties. Mix them up with the other three and a routine rotation becomes an incident call.

Key lifecycle: DKG, signing, refresh, resharing, retirement Distributed key generation creates the key. Signing consumes it. Refresh and resharing both change share material while leaving the public key and address unchanged. Retirement ends the wallet and requires moving assets first. DKGDistributed Key Generation: every party contributes randomness and proves it played fair; the key is never assembled in one place, not even during setup.Signing RefreshReshare Retire Refresh is not a one-time step like the others: it repeats throughout the wallet's life, cycling back into ordinary signing each time. repeats: quarterly & after suspected host compromise public key & address unchanged import path =full-key moment sweep first Below-threshold survivors cannot reshare Fall below t surviving shares and the address is permanently frozent is the signing threshold — the minimum number of shares required to sign or reshare (t=2 in a 2-of-3 wallet). Fewer than t shares can never combine into a signature again.
The loop shows refresh recurring on its own schedule and handing control back to ordinary signing each time — it does not run before every signature. Refresh and reshare swap out share material while the funds sit still; the other three either change the address or end the wallet.

Key lifecycle

Distributed key generation

Every party contributes randomness and proves it played fair. The full private key is never assembled, so there is no moment when one machine could have copied it.

Concrete use: For a 2-of-3 wallet, retain the DKG transcript hash, participant identities, public key, and independently derived first address.

Failure mode: Import an existing seed and split it afterward and the whole key sat on one machine first. Whatever was watching that machine has it.

Signing

Each participant checks the same canonical payload, burns one presign package if the protocol uses them, and the group emits a signature the chain cannot tell apart from a single-key one.

Concrete use: Bind request ID wd_20260831_0042, chain ID, nonce, asset, amount, destination, fee ceiling, and policy decision into the audit record.

Failure mode: A quorum will happily sign a payload someone else chose. Compromise the policy engine and the cryptography works perfectly against you.

Proactive refresh

Every share gets re-randomized while the public key and address stay put. Shares from the old epoch and the new one will not combine, so an attacker who stole one last quarter is left holding a dead number.

Concrete use: Refresh quarterly and after a suspected host compromise; prove completion on all three parties before deleting epoch N material.

Failure mode: A refresh job nobody has restore-tested is a scheduled task you hope works. You find out during an incident.

Resharing

A live quorum hands a fresh set of shares to a different group, or changes t-of-n, and the funds never move.

Concrete use: Replace a departing 2-of-3 signer with a new HSM and verify the unchanged public key before revoking the old share.

Failure mode: Resharing needs a live quorum. Drop below t surviving shares and there is nothing left to reshare with, and the address is frozen for good.

Retirement

Sweep the assets out first, then destroy every live share and presign cache. Keep the non-secret audit evidence, because that is what you show later.

Concrete use: After a chain is delisted, sweep all derivation paths, reconcile zero balances, then obtain destruction attestations from each domain.

Failure mode: Delete the vendor workspace with dust or a forgotten token balance still on those addresses and the value is stranded, with nothing left that can sign for it.

Share custody topology

For each row, ask what a single attacker has to own to reach two shares. Count IAM roles, hypervisors, update channels, operators, regions, and whoever holds recovery authority. Do not count machines.

TopologyCorrelated failureLivenessRecoveryCollusion floor
3 VMs / one cloud account / one IAM roleBROKENFastEasyOne admin credential
Separate cloud accounts, same providerCONDITIONALHighModerate2 account compromises
Two cloud providers + on-prem HSMDIVERSEMediumHarder2 trust domains
Vendor 2 shares + customer HSM shareVERIFYVendor-dependentExit package requiredVendor + customer or vendor internal quorum
Mobile approver + cloud + HSMDEVICE RISKHighUser lifecycle heavy2 device/domain compromises

What MPC does not protect

Policy-engine compromise

An attacker-crafted request that the policy engine approved looks exactly like a legitimate one to the signers. Splitting the key does nothing here.

Concrete use: Require an independently operated callback to compare the payload with ledger intent before any share acts.

Failure mode: One admin over both the policy engine and the shares collapses the whole design back to a single key.

Blind signing

An approver staring at a 32-byte hash has no way to tell where the money goes or what contract call they just authorized.

Concrete use: Decode EIP-712 or chain-native intent on a separate trusted display and bind it to the request.

Failure mode: The screen says one thing and the bytes reaching the signer say another. The approval is real; the description was fiction.

Address substitution

Malware waits for the business approval, then swaps the destination address before the transaction is serialized. Everyone signed what they thought they were signing.

Concrete use: Use allowlists with a 48-hour activation delay and out-of-band confirmation for additions.

Failure mode: Eyeballing the first and last four characters catches nothing. Attackers grind vanity addresses that match both ends.

Threshold insider collusion

The protocol cannot tell an honest quorum from a corrupt one. t valid participants who agree to steal is exactly what the design authorizes.

Concrete use: Set role separation so two approvers cannot also administer policy or signer infrastructure.

Failure mode: If a service account drives two of the three shares, your 2-of-3 needs zero humans to sign.

Missing attribution

All the chain ever sees is one signature. Which parties took part, and which ones declined, exists only in whatever you logged.

Concrete use: Write append-only participant, policy, payload, and transcript hashes to an external audit store.

Failure mode: The privacy that makes MPC look like a normal wallet is the same property that costs you free on-chain attribution.

Supply-chain compromise

A tampered dependency or signer image can bias nonces, leak share material a few bits at a time, or rewrite payloads on the way in.

Concrete use: Pin reproducible builds, SBOM, signatures, audit commit, and measured boot evidence.

Failure mode: The proof covers the paper. It says nothing about the binary you are running.

Custody primitive decision matrix

Pick MPC when you need many chains and an address that survives staff changes. Pick native multisig when you want a cold quorum anyone can verify from the chain itself. Split hot and cold across both when your biggest worry is the vendor.

PrimitiveOn-chain footprintQuorum changeAttributionExit failure
Threshold MPCOrdinary single signatureSame address via reshareOff-chain log onlyNeed export/reshare package
Native multisigVisible; chain-specific feeUsually new policy/addressOften visibleIndependent signers can survive coordinator
Smart-contract walletContract call + execution gasUpgradeable policyEvent/log dependentChain and contract governance remain
Single-key HSMOrdinary signatureRe-key requires moveHSM audit logBackup/key ceremony determines survival
Hybrid MPC hot + multisig coldTier-dependentIndependent pathsMixedReduces common vendor failure

Vendor due-diligence checklist

The protocol name on the datasheet is where diligence starts. Everything below is what you still have to make them show you.

  1. Name the protocol, revision, ciphersuite, implementation commit, and every production audit.
  2. Prove DKG was used; document any full-key import path and when it is allowed.
  3. Map shares to independent IAM, cloud, region, operator, HSM, backup, and update domains.
  4. Ask for evidence of refresh and resharing runs that finished, with timestamps. A screenshot of the settings page proves nothing.
  5. Explain malformed-proof validation, nonce handling, presign reuse prevention, and identifiable abort.
  6. Separate policy administration from signer administration and require quorum for policy changes.
  7. Get the export package in writing, then restore from it in an isolated environment and sign something with it.
  8. Measure signing availability for the chosen quorum; alert before survivors fall below threshold.
  9. Retain payload and participant attribution outside the vendor's trust domain.
  10. Test vendor disappearance, customer-share loss, cloud outage, and revoked operator scenarios.

Common mistakes & anti-patterns

Every one of these sails through a vendor demo. Expand one for the control and why it still fails.

Seed import called MPC

Splitting a key that already exists is secret sharing. It gives you the same runtime story as real DKG, minus the one guarantee that mattered.

Concrete use: Mark imported wallets as a distinct assurance class.

Failure mode: Calling it MPC afterward does not un-happen the moment the whole key existed in one place.

One-manager quorum

Three approvers who all report to the same VP can all be pressured, or fired, by the same person.

Concrete use: Require independent reporting lines for high-value tiers.

Failure mode: The org chart quietly undoes the separation the architecture diagram promised.

ECDSA-only selection

An ECDSA-only threshold stack cannot sign for Ed25519 chains like Solana or Cardano. Vendors bridge that gap with raw signing.

Concrete use: Inventory chain signature schemes before procurement.

Failure mode: Raw signing hands the signer bytes nobody parsed, so amount and destination limits never get a chance to fire.

No exit rehearsal

You have exportability once a second implementation has actually restored the shares and produced a valid signature. Until then you have a promise.

Concrete use: Run an annual isolated restore using the contractual package.

Failure mode: The day you need the exit package is the worst possible day to learn the procedure was never run.

Primary sources & scope

Every operational claim above was checked against these first-party documents on 2026-08-31. The examples are illustrative controls, not legal, investment, or vendor-selection advice.