Operator service (planned)

Operator design

Split auditor-key custody, scoped audit requests, disclosure outputs and allow/deny lists. Designed, not built.

Designed, not built

Nothing on this page runs. It summarises the design in docs/OPERATOR-DESIGN.md, written on 2026-10-05.

What the operator is

OpenZeppelin Confidential Tokens and Nethermind's Stellar Private Payments (SPP) both define compliance roles and leave them to whoever deploys them. The operator would run those roles for issuers and pool operators:

  • auditor-key custody;
  • scoped audit requests;
  • selective-disclosure outputs, including tax export;
  • allow and deny lists.

Confidential one-to-many payouts remain the first use case.

Where the demand comes from

The written record is narrower than some earlier research said. SDF's 2026-08-06 developer meeting notes, written by Kaan Kacar, contain:

  • in his own voice: "Nobody is building that platform for you. Hint.";
  • his paraphrase of Alessandro Voto, SDF's privacy product manager: "go be the operator — sanction lists, allow/deny lists, compliance hooks".

The notes also carry design guidance that this design follows: the auditor key "should sit unused inside an MPC or TEE custody setup … and only answer scoped requests when a regulator compels one".

Other asks quoted elsewhere came from video captions that could not be checked. There is no statement from SDF, OpenZeppelin or Nethermind that they will not build this themselves. Sources: docs/research/DEMAND-QUOTES.md.

Who takes part

PartyTrusted forNot trusted for
HolderTheir own keys and disclosuresCompleteness: a holder can leave things out
Issuer or pool operatorDeciding whether to freeze, claw back or listDecrypting alone, or proving a clawback alone
Requester (regulator, auditor, tax authority, or the holder)Holding its own disclosure keyReceiving more than the approved scope
Custodians (issuer, Tally, an independent party)Their own key share and their own scope checkActing below the threshold
TallyThe request workflow, archive, list projections, log and one key shareDecrypting alone or holding a quorum

The design rule: no single party, Tally included, can decrypt an amount, prove a clawback or change a list on its own.

Auditor-key custody

The protocols fix several things:

  • On OpenZeppelin Confidential Tokens, the auditor key is one Grumpkin scalar per auditor_id. The registry accepts any valid point with no proof of possession, and rotation overwrites the key in place.
  • On SPP, the view key is one Baby JubJub scalar that cannot be rotated and must exist before the pool is deployed.
  • Decryption is linear in the key in both systems.

Options compared

OptionWho can decrypt aloneVerdict
Tally holds the key in an HSMTallyRejected: breaks the design rule
The issuer holds its own key; Tally supplies softwareThe issuerSupported as a mode, but it is tooling, not an operator
Threshold custody, two-of-three, with threshold decryptionNobody below the thresholdChosen for routine decryption
A commercial MPC custody productNobody below the vendor's thresholdOnly if it supports these curves; unverified and unlikely; an open question
A trusted execution environment holding the keyThe enclave, if brokenUsed only for a short proving step

The chosen design

  • Custodians. The issuer's compliance function, Tally, and an independent custodian chosen by the issuer.
  • Separation. The issuer's freeze and clawback signers must not hold a quorum of shares.
  • Key generation. The key is generated jointly, and a proof of possession is published, because the registry checks none.
  • Who opens a result. The requester combines the partial results. Custodians encrypt their contributions to the requester's key, so only the party entitled to a result sees it.
  • Share upkeep. Shares are refreshed without changing the public key. Every historical key version is kept.

The weakest point. Clawback and auditor-side disclosure proofs need the whole key inside one proof. The design reassembles the key briefly inside an attested enclave, only for a logged, approved request, and publishes the attestation. Two alternatives, a collaborative prover or a circuit change, are open questions for SDF and OpenZeppelin.

Standing balance openings are as sensitive as the key, so they are held secret-shared among the same custodians.

Scoped audit requests

A request names:

  • the issuer and contract;
  • the requester and its disclosure key;
  • a legal basis;
  • the subjects (accounts or note keys);
  • a ledger range;
  • the data wanted;
  • the output type;
  • an expiry;
  • a notification rule.
RequesterApprovals before any custodian contributes
A holder, about their own accountsTheir own signature; no custodian decryption needed
The issuer's compliance functionIssuer signature plus the independent custodian's scope check
A regulator or courtIssuer signature (or documented compulsion), plus the independent custodian's and Tally's scope checks
Anyone elseRefused

Scope is enforced cryptographically:

  • Custodians compute their part only for events they resolve themselves from at least two archives.
  • They never accept event data from the requester.
  • Each contribution is bound to the request and the event.

Every request, approval, refusal, contribution and enclave session is written to a hash-chained log. Custodians countersign the log daily, and its head is anchored on Stellar daily.

Disclosure outputs

OutputProduced byComplete?State
Aggregate total of a payout roundPayerYes, for the declared lanes and windowBuilt
Per-period total, outboundHolderYes, outbound transfers are enumerableCircuit built; verifier mode missing
Per-counterparty totalHolderYes for outboundMissing: new circuit
Inbound totalsRecipientNo: a holder can omit inbound eventsMissing
Auditor-attested totalsCustodians plus the enclave stepYesMissing
Tax exportHolder, locallyOutbound complete; inbound holder-asserted unless auditor-attestedMissing

The tax export is a verifiable transaction statement. It does no fiat valuation, no jurisdiction-specific tax calculation and no filing.

Allow and deny lists

The two systems use different list models:

  • OpenZeppelin: a yes/no policy call keyed by Stellar address. OpenZeppelin v0.9.0 ships no implementation.
  • SPP: Merkle trees keyed by note public keys. The allowlist cannot delete, and the blocklist root must match exactly at proof time.

The design keeps one off-chain subject registry and projects it into each system:

  • OpenZeppelin projection: a policy contract serving many tokens, signed two-of-three.
  • SPP projection: Tally runs the pool's association-set contracts. Removal from an allowlist becomes a blocklist entry. Blocklist updates are batched on a published schedule, with an emergency path for sanctions hits.

What exists and what is missing

AreaTodayMissing
Client for the tokenct/sdk, v0.9.0, conformance vectors passAuditor client
Disclosure circuitsAggregate n = 8, 16, 64Per-counterparty, inbound and auditor-side aggregates
Verifiertally verifyPer-period mode; historical auditor-key lookup
Key custodyNoneJoint key generation, threshold decryption, refresh, enclave proving step
Requests, log, lists, archive, tax exportNoneAll of it

The full threat table is on Threat model. The questions this design leaves open are on Open questions.