Open sourcing a FROST threshold-custody library for shielded ZEC

We’ve been running 2-of-3 threshold custody of a shielded Zcash address for our own project. I just pulled out the part that isn’t specific to us and open sourced it:

It integrates the Foundation’s reddsa FROST over RedPallas and reimplements none of it. Threshold signing fails silently and totally when you get it wrong.

What it adds is the distance between a signature and a transaction. frost-rerandomized gives you a signature. It does not give you a Zcash transaction. In between:

  • DKG over an encrypted transport (x25519 + ChaCha20-Poly1305), so no dealer ever holds the whole key
  • The daemon each share-holder runs, and the protocol it speaks. Everything crossing the wire is public: sighash, randomizers, nonce commitments, signature shares. The share never crosses, and the coordinator holds no share at all.
  • Note selection, witness tracking, change, and Orchard spend assembly
  • Deposit scanning: confirmation depth, reorgs, deduplication, ordering

Status: Running on testnet. We will test with mainnet ZEC in the coming week. It has not been independently audited as a whole product. And below threshold there is no recovery: no onchain policy to fall back on the way an EVM multisig contract has, so share backup is the whole safety story. Treat it as something to read and criticise, not to put funds behind today.

Where I’d genuinely value input:

  1. Does this overlap with the planned FROST integration into zcash-devtool and the DKG work on the roadmap? I’d much rather build above that than beside it, and I’d rather find out now than later.
  2. In our case the custodians here are always-on machines, and I think that’s right for a treasury: a vault that can’t pay because a phone is asleep is worse than one held by three machines run by three different people. FROST is interactive: round one commits a nonce to a specific sighash, so participants must be reachable after a transaction is proposed and stay alive through both rounds.
    What I’m less settled on is where the human sits. What organisations actually ask for is “three colleagues approve a payment,” and the obvious reading, shares on phones, fights the protocol hard: you end up needing pre-committed nonce pools, and nonce reuse leaks the share.
    The alternative is to separate authorisation from participation. The share stays on always-on infrastructure; the owner’s device gates it with a plain signature over the proposed transaction, and the custodian won’t enter round one without one. Named human approval, no share on a device that sleeps, no nonce pool.
    Has anyone worked this through for Zcash? Is separating approval from signing the obvious answer, or is there a reason to want shares on personal devices that I’m missing?

3. Anyone custodying shielded funds for an organisation today: what do you actually do right now? I suspect the honest answer is often “one person holds the seed,” and I’d like to know whether that’s right.

Happy to hear about your opinions!

I’ve built out a FROST-based wallet and have tested it both on testnet and mainnet. Still quite a few UX things to fix, but it works. Just leveraging the frost-tools crates and provide options to run/coordinate the frostd server in app.

The coordination piece is a tough one and I try to provide optionality with the server running/cooridnation piece:

  • Dedicated url - someone can host the server on a dedicated url
  • Disposable URL/Tunnels - Cloudflared ‘one-time’ use tunnels to coordinate across
  • Tailscale Serve - Users are independently connected to a magicDNS as long as they are in the same network

Once users are connected to a single server, it behaves similarly to a Gnosis Safe-like build that users can build txs and sign off on them. That is the feeling I was shooting for in building this, more as a coordination tool for DAO-like structures.

1 Like