Threshold (FROST) custody for shielded ZEC: design check before a ZCG application

Hi all.

I’m an independent dev with an applied-cryptography background (ZK and lattice work, mostly), and I’ve been circling the shielded-custody gap on Zcash for a while. Before I write a ZCG application around it, I want to sanity-check the scope with this community, mostly because I’d rather find out now if I’m missing something or stepping on work that’s already in flight.

The thing that bugs me: an org that wants to hold shielded ZEC today basically can’t do it without either a single key or a single custodian. Even the dev-fund lockbox (ZIP-271) sits in a transparent 2-of-3 P2SH, and the largest corporate holder keeps ~290k ZEC with one custodian. Meanwhile the pieces to fix this have quietly come together: FROST 3.0 shipped, frost-rerandomized handles Orchard-style spend auth, PCZT gives you multi-party tx assembly, and the Hackmas work wired zcash-devtool and frost-client together for a signing session. ZF’s own “State of FROST” post said the missing piece is wallet adoption, and “easy multi-sig tools for shielded addresses” is on the ZCG wishlist. So the primitives exist. What’s missing is someone assembling them into something an org would actually trust.

Before writing any of this up I wanted to be sure the primitives hold together on the current network and not just in the demo. So this past week I reproduced the FROST-over-PCZT flow end to end on testnet, and then pushed it onto the Ironwood pool. Short version: I have a 2-of-3 rerandomized-FROST signature authorizing a real Ironwood shielded spend, mined on testnet (txid a5533fe7...487d, height 4164791). I’m happy to share the full reproduction. The public testnet explorers are lagging badly right now (the one I checked is a month behind the tip), so the repro is honestly more useful than the txid if anyone wants to verify.

Getting there surfaced two things I think matter for scoping:

  1. zcash-devtool (pczt 0.7 / orchard 0.15) and frost-tools’ zcash-sign (pczt 0.5/orchard 0.11) don’t interoperate anymore. zcash-sign can’t even parse a devtool PCZT. The two ZF tools have drifted apart since Hackmas.

  2. On post-NU6.3 testnet everything lands in Ironwood, and the FROST tooling only knows Orchard. zcash-sign injects into the Orchard bundle, and devtool’s own pczt update-with-signature has the shielded path stubbed with a literal TODO: Maybe support this for both Orchard and Ironwood. Ironwood spend auth is still RedPallas and
    rerandomizable (devtool’s source even calls Ironwood spends “Orchard-shaped”), so FROST
    is clearly the right primitive. But as far as I can tell nothing ships that actually
    signs an Ironwood spend. I bridged it with two throwaway tools (an Ironwood-aware
    external-sig injector and a small non-interactive rerandomized signer) purely to prove
    the point. They’re demo glue, not a product. But they made the gap concrete: this works
    on the pool that becomes mainnet default on July 28, and nothing assembles it.

Roughly what I’d want to build, three milestones:

  1. A real DKG ceremony (not trusted-dealer, which rather defeats the purpose) plus rerandomized signing over PCZTs, targeting Ironwood, and a DKG interoperability spec
    drafted together with ZF.
    2. A coordinator service and hardware-signer integration. Keystone first, since its
    shielded PCZT signing actually shipped; Ledger’s Orchard path is merged to their dev
    branch but not in a release yet.
    3. A viewing-key audit layer: UFVK read access to balances, memos, an exportable ledger.
    The boring middle that no org-grade tool covers.

Desktop/CLI first, and honest about the trust model: no party moves funds, everything auditable through viewing keys.

Two things I want to get ahead of:

  • There have been a couple of multisig-for-shielded proposals before that didn’t ship. I don’t want to relitigate those. I think the difference this time is that I’m showing up with working code on the current pool and a concrete spec contribution rather than a plan, but if people think those earlier attempts stalled for some other reason (scope, trust model, long-term maintenance), I’d genuinely rather hear it now than after I apply.
  • Also, @mahmudsudo recently posted a FROST shielded multi-sig SDK proposal. I don’t see that as competing. A clean SDK over the ZF stack is useful, and I’d rather build on top of it than reinvent that layer. My scope is the product and service around it (the ceremony, coordinator, hardware, audit), plus the Ironwood and interop work that layer would need too. Glad to coordinate so we’re not duplicating effort.

Where I’d most like input, especially from @conradoplg and anyone at ZF:

  • The DKG interop spec. “State of FROST” flagged the missing key-generation standard as
    the thing limiting interoperability, and ZIP-312’s non-requirements explicitly leave DKG
    out of scope. Is anyone already drafting this? Would ZF be open to co-authoring, and is
    ZIP-312 the right home or is this a new ZIP?

  • Ironwood. Is there work in flight to bring frost-tools / zcash-sign up to v6 and the
    Ironwood pool that I should build on instead of my throwaway injector? I’d much rather
    the real signing path live upstream than in my code.

  • Trusted-dealer vs DKG for the ceremony. ZIP-312 notes DKG precludes seed-phrase
    recovery. For org custody I lean toward DKG with a documented recovery story, but I’d
    like a reality check.

  • Anything here that overlaps with ZODL / ECC / ZF roadmap work I’m not seeing.

If this is broadly the right shape I’ll turn it into a proper ZCG application with milestones and a budget. Mostly I want to make sure I’m scoping something the protocol folks actually want. Thanks for reading, and I’ll happily post the reproduction steps if there’s interest.

P.S. The application GitHub link as per Alex’s request: Grant Application - Threshold (FROST) custody for shielded ZEC · Issue #358 · ZcashCommunityGrants/zcashcommunitygrants · GitHub

2 Likes

The intent is to change ZIP-312 to bring DKG into scope, mostly due to quantum recoverability, see ZIP 2005: Ironwood Quantum Recoverability , the idea is to also use C2SP/cocktail-dkg.md at main · C2SP/C2SP · GitHub for the DKG (draft PR) since it allows generating additional key material required for Zcash use, but that spec is still a draft and I’ve been providing feedback to it and it looks almost close to be deployable IMO.

The ZIP work was being done in https://github.com/zcash/zips/pull/895 , I need to try to get that moving again.

No one is working on this currently, but it should be easy. I might work on it in the upcoming future, IMO it’s nothing something worth being part of a grant proposal.

Look at the share recovery flow from COCKTAIL-DKG, that seems the way to go. IMO trusted dealer is kinda of useless since it defeats the main security gain of FROST (never having the key in memory ever)

Nothing that I am aware of.

I think the biggest challenge is simply the UI part of it all. In my mind the ideal solution would be to Zodl wallet to support FROST, but that might be tricky to write a grant proposal for. Other approaches might be do a specific wallet from scratch, or try with other wallet.

Also be aware that Zkool already supports FROST, though I am not a fan of their specific messaging approach which is neat but super slow (it uses the Zcash blockchain itself) and does not have the polished UI that Zodl has.

BTW, the messaging is also another tricky part, we have FROST server but for real world usage it needs integration with e.g. Tor; a full P2P solution would be best (but harder)

1 Like

Just want to point out its been working for a while and I am a fan. We also have multiple Frost hackathon submissions in route, stay tuned. (Check ZecHub PR’s for the goods )

2 Likes

Agreed, and taken. It was multiple lines once I found the seam, so it’s out of the proposal. I’ll clean the injector up and PR it to frost-tools this week. If you’d rather write it yourself, say so and I’ll stay out of your way, genuinely no ego about it.

This changed my thinking most. I’d assumed the key-generation gap was open and that I could help draft something; it isn’t, so I’d rather be the implementation that helps #895 and #1032 move than another author.

One question from reading ZIP-2005 and cocktail-dkg together. ZIP-2005 has the participants agree on sk and each retain qsk, and says losing qsk loses the funds once Orchard is disabled. The sk contributions look like they belong in COCKTAIL’s optional application payloads, with the extension derived from them so the transcript enforces agreement. But recovery’s output is only x_i, Y and the verification shares: step 6 decrypts the whole plaintext and keeps just the leading scalar, so the payload sits right there and gets dropped. Read literally, recovery hands back a signing share and quietly loses qsk.

And ZIP-2005’s answer for qsk backup is ZIP-32 re-derivation from the seed, then it says a deployment not using ZIP-32 is on its own. A DKG group is exactly that deployment, with no seed to fall back on, which is rather the point.

So: should recovery return the payloads, or is the application meant to dig them out itself? Happy to write it up on the C2SP issue if it’s real and I’m not misreading.

Agreed. It was only ever how I got a first signature out of the stack.

I hadn’t clocked that, which is a hole in my homework, so I read it before replying rather than after. Credit where it’s due: real DKG, no trusted dealer, a GUI, mainnet since last July. Further along than I’d assumed anyone was.

@hanh, a sanity check if you have a minute.
As far as I can tell the FROST signing path only walks the Orchard actions and calls sign_orchard_with, and DKG mints an Orchard-only UA; ironwood_indices turns up in the Ledger builder but not in frost/. So Zkool’s threshold accounts are Orchard accounts. Have I got that right, or is there an Ironwood path I’ve missed?

You’re right that it’s the hard part, though I’d argue about where it lives. “My savings need two of my three devices” belongs in a wallet, and Zkool is most of the way there. “Five people, a policy, an auditor, hardware, and a recovery drill” is a different animal, whose hard parts are the ceremony, the recovery and the audit trail, not send and receive.

What convinced me it isn’t just polish is your own recommendation. COCKTAIL says you MUST NOT use the group key for critical operations, naming long-lived asset custody, until every participant confirms they’ve stored their recovery material, and the round-1 ciphertexts must survive somewhere durable, coordinator included. Those are ceremony obligations no library discharges for you; for this use case the UI is the security work.

So I’d rather the core be an embeddable crate than a wallet feature. Then nobody writes a grant against anyone else’s roadmap, and if Zodl or Zkool wants it later it’s there. Zodl being mobile-only is a fit problem anyway: a treasury ceremony wants a desk, several people and a hardware signer on the table.

Agreed, and I can’t solve it in general. One narrowing for my case: with hardware signers the signing round can go over QR, which Keystone does anyway and devtool already has to-qr/from-qr for, so network privacy doesn’t arise for the round that authorizes money. The ceremony is the awkward one, three rounds across n participants being a lot of QR codes. My instinct is frostd behind an onion rather than inventing a transport. Would you take a Tor transport in frostd upstream, or does that belong client side?

@dismad, thanks, I looked. Found Steward in the PRs, close enough that I’m glad I read it. If the rest are visible once voting opens I’d like to go through them; I’d rather find out I’m duplicating someone this week than after I apply.

1 Like

Mainnet was ~May 2025.
Ironwood isn’t fully supported yet. But it shouldn’t be too hard
The hardest parts were:

  • secure and authenticated encrypted messaging p2p and p2g. Zcash memos gets us nearly there but authentication was added (following L/A audit report)
  • backing up all the added key material. There is no standard for it. I choose a way that makes it restorable on Zkool only. One day, someone will write a ZIP. But for now, unlike seed phrases, FROST accounts use a proprietary format.
  • there are areas I don’t cover that the FROST protocol does such as detecting malicious actors, reconfiguring the threshold, etc.
  • But for your use case, I think it should work.

Mainnet ~May 2025, noted, my mistake. I’d taken July from the workshop thread and should have asked you rather than read around you. :sweat_smile:

Thanks, that’s what I needed to know. PR on frost-tools this week regardless.

This is the part I’d like to pick up, and it’s the same hole @conradoplg and I were circling from the other side. ZIP-2005 has the participants agree on sk and each keep qsk forever, and its answer for backing qsk up is “re-derive it from your seed phrase”, which a DKG group hasn’t got. So you hit it from the wallet end and it turns up again from the quantum-recoverability end, and both times the answer is that there’s no format.

“Restorable on Zkool only” is understandable, because you had to ship something. But it’s also the specific thing an org can’t sign off on, because the recovery path for a treasury can’t be one implementation. The funds have to outlive the tool.

So if you’re willing: what’s in your format? If someone writes that ZIP it should start from whoever already had to invent one, not from a blank page. I’ll do the drafting legwork, and your name goes on it if it goes anywhere.

For two to five people holding Orchard today, I think you’re right, and I’d point them at Zkool. Where it stops for me is the org case: shares on hardware rather than in the app, an auditor with read access and no spend authority, Ironwood after the 28th (hopefully), and a recovery story that isn’t tied to one wallet. And the two you say you don’t cover, malicious-actor detection and reconfiguring the threshold, are the ones a treasury leans on hardest, since rotation is what you do when someone leaves.

1 Like

Quick one, nothing new to reply to yet, just flagging two things.

@conradoplg the issue’s up: zcash-sign: Ironwood (NU6.3 / v6) external signing — scoping, and the orchard FVK blocker · Issue #591 · ZcashFoundation/frost-tools · GitHub. Laid out where the version bump lands, orchard included. Still happy to do it if you’d rather point me at a branch than write it yourself.

@hanh separately, I’m filling out the application now. Fingers crossed it lands somewhere, and if it does I’d still take you up on the format question whenever you get a minute.