-
-
Save denniswon/32ba5dad6d44ee72de34710735a8d03e to your computer and use it in GitHub Desktop.
| --- | |
| Newton Privacy Layer vs Fairblock: Technical Comparison Analysis | |
| ★ Insight ───────────────────────────────────── | |
| This comparison covers two fundamentally different approaches to onchain privacy: | |
| - Newton extends an existing EigenLayer AVS (policy evaluation) with privacy primitives — privacy is an add-on to an existing | |
| validator network | |
| - Fairblock is a purpose-built privacy infrastructure chain (FairyRing) that exports cryptographic services to other chains | |
| - The cryptographic primitives overlap significantly (threshold DKG, IBE-like schemes), but the trust models and integration patterns | |
| diverge sharply | |
| ───────────────────────────────────────────────── | |
| --- | |
| 1. Architecture Overview | |
| Newton Privacy Layer | |
| ┌──────────────────┬───────────────────────────────────────────────────────────────────────────────┐ | |
| │ Component │ Description │ | |
| ├──────────────────┼───────────────────────────────────────────────────────────────────────────────┤ | |
| │ Secure Envelope │ HPKE (RFC 9180) encryption with AAD context binding (X25519/ChaCha20Poly1305) │ | |
| ├──────────────────┼───────────────────────────────────────────────────────────────────────────────┤ | |
| │ Authorization │ Offchain Ed25519 consent signatures validated by gateway │ | |
| ├──────────────────┼───────────────────────────────────────────────────────────────────────────────┤ | |
| │ Operator Network │ Existing EigenLayer AVS operators hold threshold key shares │ | |
| ├──────────────────┼───────────────────────────────────────────────────────────────────────────────┤ | |
| │ Gateway │ Trusted intermediary (Phase 1.5) → replaced by threshold DKG (Phase 2) │ | |
| ├──────────────────┼───────────────────────────────────────────────────────────────────────────────┤ | |
| │ Storage │ Encrypted data refs stored in gateway PostgreSQL (encrypted_data_refs table) │ | |
| └──────────────────┴───────────────────────────────────────────────────────────────────────────────┘ | |
| Data Flow (Phase 1.5 — current target): | |
| Client → HPKE encrypt to gateway pubkey → store encrypted envelope in DB | |
| → createTask with encrypted_data_refs | |
| → Gateway decrypts (single trusted party) | |
| → Operators evaluate policy on plaintext | |
| → BLS aggregate signatures → respond on-chain | |
| Data Flow (Phase 2 — future): | |
| Client → HPKE encrypt to threshold pubkey (DKG-derived) | |
| → Prepare Phase: each operator produces partial decryption | |
| → t-of-n threshold decryption reconstructs plaintext | |
| → Operators evaluate policy → BLS sign → aggregate | |
| Fairblock | |
| ┌───────────────────┬───────────────────────────────────────────────────────────────────────┐ | |
| │ Component │ Description │ | |
| ├───────────────────┼───────────────────────────────────────────────────────────────────────┤ | |
| │ FairyRing │ Cosmos SDK app-chain for decryption key management │ | |
| ├───────────────────┼───────────────────────────────────────────────────────────────────────┤ | |
| │ x/keyshare module │ Manages DKG, validator keyshare submission, aggregation │ | |
| ├───────────────────┼───────────────────────────────────────────────────────────────────────┤ | |
| │ x/pep module │ Pre-execution privacy: stores encrypted txs, decrypts at target block │ | |
| ├───────────────────┼───────────────────────────────────────────────────────────────────────┤ | |
| │ FairyPort │ IBC/cross-chain relayer for key distribution │ | |
| ├───────────────────┼───────────────────────────────────────────────────────────────────────┤ | |
| │ FairyKits │ Integration SDKs for Cosmos, EVM, RustVM chains │ | |
| ├───────────────────┼───────────────────────────────────────────────────────────────────────┤ | |
| │ Encryption SDK │ Client-side browser encryption (no third-party dependency) │ | |
| └───────────────────┴───────────────────────────────────────────────────────────────────────┘ | |
| Data Flow: | |
| Client → encrypt tx with Master Public Key + condition ID (e.g. block height) | |
| → submit encrypted tx to destination chain (stored in x/pep) | |
| → FairyRing validators monitor conditions | |
| → When condition met: validators submit keyshares | |
| → On-chain aggregation (2/3+1 threshold) | |
| → Aggregated key relayed to destination chain | |
| → x/pep decrypts + executes tx at BeginBlock | |
| --- | |
| 2. Cryptographic Primitives Comparison | |
| ┌─────────────────┬──────────────────────────────────────────────────┬───────────────────────────────────────────────────────────┐ | |
| │ Dimension │ Newton Privacy Layer │ Fairblock │ | |
| ├─────────────────┼──────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤ | |
| │ Core Encryption │ HPKE (X25519, HKDF-SHA256, ChaCha20Poly1305) per │ Threshold IBE (Boneh-Franklin on BLS12-381) + hybrid │ | |
| │ │ RFC 9180 │ ChaCha20Poly1305 │ | |
| ├─────────────────┼──────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤ | |
| │ Key Exchange │ X25519 Diffie-Hellman (DHKEM) │ Identity-Based Encryption (condition = "identity") │ | |
| ├─────────────────┼──────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤ | |
| │ Threshold │ Pedersen DKG (Phase 2, planned) │ Joint Feldman DKG (implemented, live) │ | |
| │ Scheme │ │ │ | |
| ├─────────────────┼──────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤ | |
| │ Signature │ Ed25519 (authorization) + BLS (attestation) │ Cosmos validator signatures │ | |
| ├─────────────────┼──────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤ | |
| │ Advanced │ MPC computation + ZK selective disclosure (Phase │ FHE (CKKS), SPDZ MPC, Twisted ElGamal, witness encryption │ | |
| │ (future) │ 3) │ │ | |
| ├─────────────────┼──────────────────────────────────────────────────┼───────────────────────────────────────────────────────────┤ | |
| │ AAD Binding │ Secure Envelope binds ciphertext to │ Condition ID binds to block height/price/event │ | |
| │ │ domain/policy/chain │ │ | |
| └─────────────────┴──────────────────────────────────────────────────┴───────────────────────────────────────────────────────────┘ | |
| ★ Insight ───────────────────────────────────── | |
| IBE vs HPKE is the key architectural divergence: | |
| - Fairblock's IBE allows encrypting to a condition (block height, price, event) without knowing the decryption key in advance — the | |
| key is derived later by validators. This enables batch decryption: one key decrypts ALL txs for that condition, saving N×S bandwidth | |
| to just S. | |
| - Newton's HPKE encrypts to a specific public key (gateway or threshold group). Decryption requires the key holder to actively | |
| participate. Each envelope must be decrypted individually. | |
| - Fairblock's IBE approach is provably more bandwidth-efficient for batch scenarios (their ePrint paper shows 99.6% bandwidth savings | |
| vs standard threshold decryption for 1000 messages). | |
| ───────────────────────────────────────────────── | |
| --- | |
| 3. Trust Model Comparison | |
| ┌─────────────────┬─────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────┐ | |
| │ Dimension │ Newton │ Fairblock │ | |
| ├─────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤ | |
| │ Phase 1.5 │ Gateway is a single trusted decryptor — │ N/A (already threshold from start) │ | |
| │ (current) │ full plaintext access │ │ | |
| ├─────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤ | |
| │ Phase 2 │ t-of-n threshold — no single operator sees │ 2/3+1 validator threshold for key aggregation │ | |
| │ (planned) │ plaintext │ │ | |
| ├─────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤ | |
| │ Validator Set │ EigenLayer restaked operators (ETH economic │ Cosmos SDK validators (staked FAIRY tokens) │ | |
| │ │ security) │ │ | |
| ├─────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤ | |
| │ Slashing │ EigenLayer slashing conditions │ Custom slashing: slash_fraction_no_keyshare, │ | |
| │ │ │ slash_fraction_wrong_keyshare │ | |
| ├─────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤ | |
| │ Key Custody │ Operators hold HPKE key shares (Phase 2) │ Share Generation Client creates MSK each epoch, splits to │ | |
| │ │ │ validators, destroys MSK │ | |
| ├─────────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤ | |
| │ Compliance │ Offchain Ed25519 consent signatures; audit │ Selective per-transaction disclosure; OFAC/MiCA compatible │ | |
| │ │ trail │ │ | |
| └─────────────────┴─────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────┘ | |
| Newton's trust evolution: | |
| - Phase 1.5: Centralized trust — gateway sees all plaintext (stepping stone) | |
| - Phase 2: Threshold trust — t-of-n operators, no single party decrypts | |
| - Phase 3: MPC + ZK — computation on encrypted data, selective disclosure | |
| Fairblock's trust model: | |
| - Threshold from day one — 2/3+1 validators must collude to compromise | |
| - Epoch-based key rotation — MSK destroyed after distribution | |
| - On-chain aggregation — key reconstruction happens transparently on FairyRing | |
| --- | |
| 4. Decryption Model Comparison | |
| ┌──────────────────┬──────────────────────────────────────────────────────┬──────────────────────────────────────────────────────┐ | |
| │ Dimension │ Newton │ Fairblock │ | |
| ├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤ | |
| │ Trigger │ Task creation (explicit RPC call) │ Condition satisfaction (block height, price, event, │ | |
| │ │ │ ZK proof) │ | |
| ├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤ | |
| │ Granularity │ Per-envelope (each encrypted data ref decrypted │ Per-condition (one key decrypts ALL txs under that │ | |
| │ │ individually) │ condition) │ | |
| ├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤ | |
| │ Timing │ On-demand during Prepare Phase │ Automatic at BeginBlock when condition met │ | |
| ├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤ | |
| │ Bandwidth │ O(N × t) for N envelopes with t-of-n threshold │ O(S) for S validators, regardless of N encrypted txs │ | |
| ├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤ | |
| │ Privacy Window │ Until operator decrypts during task evaluation │ Until condition is satisfied (can be indefinite) │ | |
| ├──────────────────┼──────────────────────────────────────────────────────┼──────────────────────────────────────────────────────┤ | |
| │ Who Sees │ Operators (during policy evaluation) │ Destination chain (after BeginBlock decryption) │ | |
| │ Plaintext │ │ │ | |
| └──────────────────┴──────────────────────────────────────────────────────┴──────────────────────────────────────────────────────┘ | |
| ★ Insight ───────────────────────────────────── | |
| Fairblock's conditional decryption is fundamentally more expressive. Newton decrypts when someone requests it (consent-gated). | |
| Fairblock decrypts when arbitrary on-chain conditions are met — block height, price feeds, ZK proof verification, governance vote | |
| deadlines. This enables use cases like sealed-bid auctions and MEV protection that Newton's consent model doesn't naturally support. | |
| However, Newton's consent model is more suited for compliance-oriented privacy — user controls who sees their data and when. | |
| Fairblock's condition-based model is more suited for market fairness (everyone's data revealed simultaneously). | |
| ───────────────────────────────────────────────── | |
| --- | |
| 5. Cross-Chain & Integration | |
| ┌─────────────────┬───────────────────────────────────────────────────┬──────────────────────────────────────────────────────────┐ | |
| │ Dimension │ Newton │ Fairblock │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ Native Chain │ No own chain — runs on EigenLayer (Ethereum) │ FairyRing (Cosmos SDK app-chain) │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ EVM Support │ Native (ECS Fargate services on Ethereum/L2s) │ Via FairyKits + precompiles embedded in EVM │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ Cosmos Support │ Not supported │ Native via x/pep module + IBC │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ Solana Support │ Not supported │ Planned │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ Cross-Chain │ Newton's multichain architecture (source → │ FairyPort (IBC relayer) + direct FairyKit integration │ | |
| │ Relay │ destination chains) │ │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ Integration │ SDK extension (@newton-protocol/sdk) + RPC calls │ FairyKit deployment + module integration or precompile │ | |
| │ Effort │ │ │ | |
| ├─────────────────┼───────────────────────────────────────────────────┼──────────────────────────────────────────────────────────┤ | |
| │ User Experience │ Encrypt via SDK, submit via RPC │ Encrypt in browser with Encryption SDK, submit to │ | |
| │ │ │ destination chain directly │ | |
| └─────────────────┴───────────────────────────────────────────────────┴──────────────────────────────────────────────────────────┘ | |
| --- | |
| 6. Product & Use Case Comparison | |
| ┌────────────────────────────┬─────────────────────────────────────────────────┬──────────────────────────────────────────────────┐ | |
| │ Use Case │ Newton │ Fairblock │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ Private policy evaluation │ Core use case — privacy for Rego policy inputs │ Not applicable │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ Sealed-bid auctions │ Not natively supported │ Core use case — condition-based reveal │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ MEV/frontrunning │ Not designed for this │ Core use case — pre-execution encryption │ | |
| │ protection │ │ │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ Private governance │ Possible via privacy extension │ Native support via encrypted votes │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ Confidential stablecoins │ Not in scope │ StableTrust product (Twisted ElGamal + FHE) │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ Compliance/KYC privacy │ Core design — consent-gated selective │ Supported via post-execution selective │ | |
| │ │ disclosure │ disclosure │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ DeFi order privacy │ Possible but not primary │ Protected Trading product │ | |
| ├────────────────────────────┼─────────────────────────────────────────────────┼──────────────────────────────────────────────────┤ | |
| │ Private AI inference │ Not in scope │ Planned (FHE + MPC) │ | |
| └────────────────────────────┴─────────────────────────────────────────────────┴──────────────────────────────────────────────────┘ | |
| --- | |
| 7. Maturity & Implementation Status | |
| ┌────────────────────────────┬──────────────────────────────────────────────────┬─────────────────────────────────────────────────┐ | |
| │ Dimension │ Newton │ Fairblock │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Phase 1 (Foundation) │ 88% complete — HPKE, Ed25519, Secure Envelope, │ ✅ Live — IBE, DKG, keyshare aggregation, │ | |
| │ │ DB storage │ public testnet │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Phase 1.5 (Gateway │ 25% complete — gateway as trusted decryptor │ N/A (skipped centralized step entirely) │ | |
| │ Decryption) │ │ │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Phase 2 (Threshold DKG) │ 0% — Pedersen DKG, threshold decryption planned │ ✅ Live — Joint Feldman DKG with validator key │ | |
| │ │ │ shares │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Phase 3 (MPC/ZK) │ 0% — MPC framework, ZK selective disclosure │ In progress — CKKS FHE, SPDZ, confidential │ | |
| │ │ planned │ transfers │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Phase 4 (Ecosystem) │ 0% — L2 deployment, operator onboarding planned │ Active — Arbitrum, CoW Swap, AltLayer │ | |
| │ │ │ integrations │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Funding │ Self-funded (Magic Labs / Newton Foundation) │ $2.5M pre-seed (Galileo, Lemniscap, Dialectic, │ | |
| │ │ │ etc.) │ | |
| ├────────────────────────────┼──────────────────────────────────────────────────┼─────────────────────────────────────────────────┤ | |
| │ Team/Origin │ Extension of existing Newton Prover AVS │ Academic research from U of Waterloo (ePrint │ | |
| │ │ │ 2022/1066) │ | |
| └────────────────────────────┴──────────────────────────────────────────────────┴─────────────────────────────────────────────────┘ | |
| --- | |
| 8. Pros & Cons | |
| Newton Privacy Layer | |
| Pros: | |
| 1. Leverages existing infrastructure — EigenLayer economic security, existing operator set, existing BLS aggregation. No need to | |
| bootstrap a new validator set. | |
| 2. Compliance-first design — consent-based authorization with Ed25519 signatures and audit trails is naturally suited for regulated | |
| use cases (KYC/AML). | |
| 3. Progressive decentralization — pragmatic phased approach (gateway → threshold → MPC) reduces initial complexity and time-to-market. | |
| 4. Standards-based cryptography — HPKE (RFC 9180) is a well-audited, widely-implemented standard. No novel cryptographic assumptions. | |
| 5. Deep integration with policy evaluation — privacy is not a standalone product but an enhancement to an existing product with users | |
| (Rego policy engine). | |
| 6. Ethereum-native — no bridging, no Cosmos dependencies, no additional token. | |
| Cons: | |
| 1. Phase 1.5 is centralized — gateway as single decryptor is a significant trust assumption. One compromise exposes all privacy data. | |
| 2. No conditional decryption — decrypt-on-demand model doesn't support time-locked or condition-gated reveals (sealed auctions, MEV | |
| protection). | |
| 3. Per-envelope decryption overhead — each encrypted ref must be decrypted individually; no batch efficiency like IBE provides. | |
| 4. Narrow use case — primarily designed for private policy inputs. Not a general-purpose privacy layer for DeFi, governance, or | |
| stablecoins. | |
| 5. DKG not yet implemented — Phase 2 threshold operations are planned but 0% complete. The real decentralization story is still | |
| theoretical. | |
| 6. No own execution layer — depends on ECS Fargate infrastructure and gateway availability. Not censorship-resistant at the protocol | |
| level. | |
| Fairblock | |
| Pros: | |
| 1. Threshold from genesis — never had a centralized decryption phase. 2/3+1 validator threshold from day one. | |
| 2. IBE bandwidth efficiency — one decryption key covers ALL transactions under a condition. 99.6% bandwidth savings vs per-tx | |
| threshold decryption (proven in ePrint paper). | |
| 3. Expressive decryption conditions — block height, price, events, ZK proofs, custom conditions. Enables sealed auctions, MEV | |
| protection, private governance natively. | |
| 4. Multimodal cryptography — IBE, FHE (CKKS), MPC (SPDZ), witness encryption, Twisted ElGamal — selects the right tool per use case. | |
| 5. Purpose-built chain — FairyRing optimized for cryptographic operations with native BeginBlock decryption and execution. | |
| 6. Broad ecosystem — Cosmos, EVM (Arbitrum), rollups (AltLayer), CoW Swap integration, Solana planned. | |
| 7. Academic foundation — published research (ePrint 2022/1066), formal security analysis. | |
| Cons: | |
| 1. Requires own chain — FairyRing is an additional trust assumption and infrastructure dependency. Users/apps depend on Cosmos | |
| validator liveness. | |
| 2. New token requirement — validators stake FAIRY tokens; adds token economics complexity and bootstrapping challenge. | |
| 3. Cross-chain latency — IBC/FairyPort relaying introduces latency between condition satisfaction and destination chain execution. | |
| 4. Not Ethereum-native — EVM support via precompiles/FairyKits, but it's fundamentally a Cosmos-first architecture. Ethereum | |
| integration is bolt-on. | |
| 5. Centralized key generation step — Share Generation Client creates full MSK before splitting. If compromised during this brief | |
| window, all keys are exposed (mitigated by destroying MSK after distribution, but the window exists). | |
| 6. Complexity — multimodal cryptography means larger attack surface and more code to audit across IBE, FHE, MPC, and ZK subsystems. | |
| 7. No consent-based model — condition-gated decryption means data is revealed when conditions are met, regardless of whether the data | |
| owner still wants disclosure. Less suited for user-sovereign privacy. | |
| --- | |
| 9. What We Can Learn from Fairblock | |
| Architectural Lessons | |
| 1. Skip the centralized stepping stone. Fairblock launched with threshold DKG from day one. Our Phase 1.5 (gateway as trusted | |
| decryptor) is a pragmatic shortcut, but it introduces a real vulnerability window and delays the trust-minimized story. Consider | |
| accelerating Phase 2 DKG to reduce time spent in the centralized trust model. | |
| 2. Conditional decryption is a powerful primitive. Newton's consent-based model ("user signs to authorize decryption") is great for | |
| compliance but limited for market fairness use cases. Consider adding condition-gated decryption as a complementary mode — e.g., | |
| "decrypt this data at block height X" or "decrypt when price oracle reports Y." This could open sealed-auction and MEV-protection use | |
| cases without building a separate product. | |
| 3. Batch decryption via IBE. Our per-envelope HPKE decryption scales as O(N×t). Fairblock's IBE allows one key to decrypt all N | |
| envelopes under the same condition. If we ever need to decrypt many privacy envelopes simultaneously (e.g., batch policy evaluation), | |
| IBE-style schemes would be significantly more efficient. Worth evaluating for Phase 3. | |
| 4. On-chain key aggregation. Fairblock aggregates keyshares on-chain (in the x/keyshare module), making the process transparent and | |
| verifiable. Our Phase 2 plans to aggregate partial decryptions off-chain during the Prepare Phase. Consider whether some aggregation | |
| should be verifiable on-chain for auditability. | |
| 5. Epoch-based key rotation with MSK destruction. Fairblock's pattern of creating a new MSK each epoch, splitting it, and destroying | |
| the original is a clean forward-secrecy model. Our Phase 2 key rotation (NEWT-174/NEWT-189) should adopt a similar | |
| destroy-after-distribution pattern. | |
| 6. Validator slashing for privacy failures. Fairblock slashes validators who fail to submit keyshares or submit wrong ones | |
| (slash_fraction_no_keyshare, slash_fraction_wrong_keyshare). Our EigenLayer operators don't currently have privacy-specific slashing | |
| conditions. Phase 2 should define slashing for operators who fail to provide partial decryptions or provide incorrect ones. | |
| Product Lessons | |
| 7. Confidential stablecoins are a market opportunity. Fairblock's StableTrust product targets a clear institutional need. Newton's | |
| privacy layer could potentially be extended to support private transfer amounts in policy evaluation (e.g., "approve this transfer | |
| without revealing the amount to validators"). | |
| 8. Client-side encryption SDK. Fairblock emphasizes that encryption happens entirely in the browser with no third-party dependency. | |
| Our Newton SDK (NEWT-182) should similarly ensure all HPKE encryption is client-local with no server round-trips for the encryption | |
| step. | |
| 9. Precompile-based integration for EVMs. Fairblock embeds cryptographic operations as EVM precompiles, making integration as simple | |
| as calling a contract. For Phase 4 L2 deployment, consider whether Newton privacy operations could be offered as precompiles rather | |
| than requiring SDK integration. | |
| What NOT to Copy | |
| 10. Don't build a separate chain. Fairblock's FairyRing adds significant infrastructure and token economics overhead. Newton's | |
| strength is being Ethereum-native on EigenLayer — no bridging, no new token, no Cosmos dependency. Keep it that way. | |
| 11. Don't over-generalize. Fairblock tries to be everything (IBE + FHE + MPC + ZK + witness encryption). Newton should stay focused on | |
| consent-gated privacy for policy evaluation and expand narrowly to compliance use cases rather than trying to cover sealed auctions, | |
| MEV protection, and confidential stablecoins simultaneously. | |
| --- | |
| 10. Strategic Positioning | |
| ┌─────────────────────────────────────────────┐ | |
| │ PRIVACY DESIGN SPECTRUM │ | |
| │ │ | |
| User-Sovereign │ Newton ◄────────────────► Fairblock │ | |
| (Consent-Based) │ "I choose who sees" "Conditions decide"│ | |
| │ │ | |
| Compliance-First │ Newton ████████████░░ Fairblock ████░░░░ │ | |
| │ │ | |
| Market Fairness │ Newton ███░░░░░░░░░░ Fairblock █████████ │ | |
| │ │ | |
| Ethereum-Native │ Newton ██████████████ Fairblock ███░░░░░ │ | |
| │ │ | |
| Multi-Ecosystem │ Newton ███░░░░░░░░░░ Fairblock █████████ │ | |
| │ │ | |
| Production Ready │ Newton ████░░░░░░░░░ Fairblock ████████░ │ | |
| └─────────────────────────────────────────────┘ | |
| Bottom line: Newton and Fairblock occupy complementary niches. Newton is consent-based, compliance-first, Ethereum-native privacy for | |
| policy evaluation. Fairblock is condition-based, market-fairness-first, multi-ecosystem privacy for DeFi/trading. The biggest | |
| actionable takeaways for Newton are: (1) accelerate Phase 2 DKG to exit the centralized trust model, (2) consider adding conditional | |
| decryption as a complementary mode, and (3) adopt epoch-based key rotation with MSK destruction from the start. |
⏺ Both saved:
- Local memory: memory/privacy-layer.md updated with full execution state, next TODOs, blocked items, and known limitations
- Supermemory: Saved as project knowledge (ID: G9S3uYwXgTYtjj9pwLL8ok) — searchable across sessions and team members
Next time you pick up Privacy Layer work, run /super-search newton privacy layer execution state to reload context, or the local
memory will auto-load from privacy-layer.md.
Newton Privacy Layer — Full Project Status
Phase 1: Foundation (HPKE + Ed25519) — 95% complete
┌──────────┬───────┬──────────────────────────────────────────────────────────────────────────────┐
│ Status │ Count │ Issues │
├──────────┼───────┼──────────────────────────────────────────────────────────────────────────────┤
│ Done │ 18 │ NEWT-180, 181, 184, 185, 186, 187, 188, 431, 432, 433, 434, 435, 436, 437, │
│ │ │ 438, 470-476 │
├──────────┼───────┼──────────────────────────────────────────────────────────────────────────────┤
│ In │ 3 │ NEWT-627 (PR #115), NEWT-182 (PR #116), NEWT-179 (PR #117) │
│ Review │ │ │
├──────────┼───────┼──────────────────────────────────────────────────────────────────────────────┤
│ Canceled │ 1 │ NEWT-183 (Ed25519 Solidity verification — not needed) │
└──────────┴───────┴──────────────────────────────────────────────────────────────────────────────┘
The 3 "In Review" issues are all SDK-side, stacked PRs. Once they merge, Phase 1 is 100%.
Phase 1.5: Gateway-Mediated Decryption — 100% complete
All 7 issues Done (NEWT-470 through NEWT-476).
Phase 2: Threshold Operations (DKG) — 0%, Backlog
┌──────────┬─────────────────────────────────────────────────┬──────────┐
│ Issue │ Title │ Priority │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-177 │ Implement DKG protocol │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-176 │ Implement threshold decryption (t-of-n) │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-174 │ Implement key rotation and refresh protocol │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-178 │ Threshold Decryption for Two-Phase Consensus │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-157 │ Implement Threshold Decryption Protocol │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-158 │ Implement DKG Protocol │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-628 │ [P2] Epoch-based key rotation + MSK destruction │ High │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-629 │ [P3] Privacy-specific operator slashing │ — │
├──────────┼─────────────────────────────────────────────────┼──────────┤
│ NEWT-630 │ [P4] On-chain aggregation commitments │ — │
└──────────┴─────────────────────────────────────────────────┴──────────┘
Canceled: NEWT-189 (duplicate of NEWT-174), NEWT-190 (operator registry — already exists via
EigenLayer), NEWT-175 (same)
Phase 3: Advanced Privacy (MPC/ZK) — 0%, Backlog
┌──────────┬────────────────────────────────────────────────────┐
│ Issue │ Title │
├──────────┼────────────────────────────────────────────────────┤
│ NEWT-167 │ MPC and ZK Proof Integration Milestone │
├──────────┼────────────────────────────────────────────────────┤
│ NEWT-171 │ Threshold Attestation Engine for BLS Aggregation │
├──────────┼────────────────────────────────────────────────────┤
│ NEWT-172 │ ZK circuit library for selective disclosure │
├──────────┼────────────────────────────────────────────────────┤
│ NEWT-173 │ Privacy-Preserving Policy Evaluation with MPC/ZK │
├──────────┼────────────────────────────────────────────────────┤
│ NEWT-631 │ [P5] Benchmark threshold HPKE + evaluate IBE batch │
├──────────┼────────────────────────────────────────────────────┤
│ NEWT-632 │ [P6] Conditional decryption (complementary mode) │
└──────────┴────────────────────────────────────────────────────┘
Canceled: NEWT-168 (MPC framework), NEWT-169 (ZK circuits for selective disclosure via SP1)
Phase 4: Ecosystem Expansion — 0%, Backlog
┌──────────┬─────────────────────────────────────────────────────────┐
│ Issue │ Title │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-159 │ DeFi protocol integration examples │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-160 │ Extend newton-cli with Privacy Commands │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-161 │ Deploy Privacy Features to L2s │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-162 │ Multi-Chain Privacy with Newton Multichain Architecture │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-163 │ Operator Onboarding with Privacy Key Generation │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-164 │ Production monitoring and alerting │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-165 │ Deploy Privacy Features to Mainnet │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-166 │ External security audit │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-170 │ Ecosystem Expansion: Production and Integrations │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-633 │ [P7] EVM precompile integration for L2s │
├──────────┼─────────────────────────────────────────────────────────┤
│ NEWT-634 │ [P8] Confidential intent evaluation │
└──────────┴─────────────────────────────────────────────────────────┘
Recommended Next Steps (SDK side)
★ Insight ─────────────────────────────────────
The Newton Privacy Layer has a clear phase gate: Phase 1 SDK PRs merging unlocks Phase 2, which is
entirely protocol-side (DKG). The SDK has no actionable Phase 2 work until the protocol implements
Pedersen DKG and epoch-based key rotation. This means the SDK team's critical path is purely about
getting the 3 stacked PRs through review.
─────────────────────────────────────────────────
Immediate (this week):
- Get PRs #115 → #116 → #117 reviewed and merged. This is the only blocker to closing Phase 1. All
code is written, tested, rebased onto latest main.
After Phase 1 closes:
2. Phase 2 has no SDK work yet — it's all protocol-side (Pedersen DKG in Rust, NEWT-177). When that
ships, the SDK will need epoch-aware public key caching and auto-refresh.
3. Potential cleanup work (not tied to privacy): the 38 noExplicitAny biome warnings in the SDK could
be addressed incrementally.
Observation — Phase 2 issue duplication:
NEWT-157/NEWT-158 overlap significantly with NEWT-176/NEWT-177. Consider consolidating:
- NEWT-157 ("Implement Threshold Decryption Protocol") ↔ NEWT-176 ("Implement threshold decryption
t-of-n") - NEWT-158 ("Implement DKG Protocol") ↔ NEWT-177 ("Implement DKG protocol")
These pairs appear to be the same work described at different times. Worth deduplicating before Phase
2 kicks off.
Newton Privacy Layer — Current State & Next Steps
Linear Issue Status
All Phase 1 + 1.5 issues are Done (14 issues). Two items remain In Review:
┌──────────┬───────────────────────────────────────────┬───────────┬─────────────────────────┐
│ Ticket │ Title │ Status │ Owner │
├──────────┼───────────────────────────────────────────┼───────────┼─────────────────────────┤
│ NEWT-179 │ Write developer integration documentation │ In Review │ AVS-side (this repo) │
├──────────┼───────────────────────────────────────────┼───────────┼─────────────────────────┤
│ NEWT-182 │ Extend Newton SDK with Privacy APIs │ In Review │ SDK-side (other device) │
└──────────┴───────────────────────────────────────────┴───────────┴─────────────────────────┘
Open PRs (Stacked Chain)
┌──────┬────────────────────────────────┬───────────────────────────────────────────────────────────────────────────┬────────────────┐
│ PR │ Branch │ Scope │ Status │
├──────┼────────────────────────────────┼───────────────────────────────────────────────────────────────────────────┼────────────────┤
│ #421 │ privacy-data-flow-fix │ Fix: privacy data via ConsensusCommitRequest.privacy_data, not │ Awaiting │
│ │ │ policyTaskData │ review │
├──────┼────────────────────────────────┼───────────────────────────────────────────────────────────────────────────┼────────────────┤
│ #422 │ multichain-routing-e2e-options │ Feat: privacy=true + two-phase + attestation options for │ Awaiting │
│ │ │ multichain-routing-e2e │ review │
├──────┼────────────────────────────────┼───────────────────────────────────────────────────────────────────────────┼────────────────┤
│ #423 │ unified-e2e-runner │ Feat: unified make e2e scenario=X runner + CI privacy/attestation steps │ Awaiting │
│ │ │ │ review │
└──────┴────────────────────────────────┴───────────────────────────────────────────────────────────────────────────┴────────────────┘
These are fixes and test infrastructure improvements to already-Done Phase 1 work. They don't unblock new tickets — they harden what's
already shipped.
★ Insight ─────────────────────────────────────
- Phase 1 AVS-side is effectively complete. The only remaining item (NEWT-179, developer docs) is low priority and already In Review.
All crypto, gateway decryption, metrics, auth, DB schema, and E2E tests are merged to main. - The stacked PRs (#421-423) close the "test gap" — before these PRs, CI had zero coverage for privacy or attestation validation. After
merge, CI will run multichain-routing-e2e privacy=true and validate_attestation=direct on every PR. - Phase 2 (Threshold DKG) is the next major engineering effort — 7 Backlog issues, all High priority. This is where Newton exits the
centralized trust model for privacy.
─────────────────────────────────────────────────
Next Steps — Priority Order (AVS-side only)
Immediate (this sprint):
- Get PRs #421-423 reviewed and merged — these are blocking CI coverage improvements
- Runtime-verify make e2e scenario=basic on dual anvil before merge of PR #423
- NEWT-179 (developer docs) — low priority but the only remaining Phase 1 AVS deliverable. Can write after PRs merge since the data flow
changed in #421
Medium-term (next sprint):
4. NEWT-627 (Enforce client-side-only HPKE encryption in SDK) — Urgent priority, but this is SDK-side work (Track B on your other
device). Blocks the SDK from accidentally doing server-side encryption.
Future (Phase 2 — not yet started):
5. NEWT-177 (DKG protocol) + NEWT-176 (threshold decryption) — the two foundational Phase 2 items. These are the highest-impact next
steps once Phase 1 closes out, but require significant design work (Pedersen DKG, t-of-n threshold scheme selection).
What's NOT Blocking
- All Phase 1.5 (gateway-mediated decryption) issues are Done
- Privacy metrics (NEWT-436) are Done and shipping
- Phase 3/4 items are all Backlog and not actionable until Phase 2 DKG is complete
- The 4 Canceled issues (NEWT-168, 175, 183, 190) were correctly deduplicated or descoped
Summary
Phase 1 + 1.5 is 97% complete on AVS-side (20/22 Done, 1 In Review, 1 In Review on SDK). The PRs in flight (#421-423) are quality/CI
improvements, not new features. Once those merge and NEWT-179 (developer docs) ships, Phase 1 is fully closed on the AVS side. The
SDK-side work (NEWT-182, NEWT-627) is being handled in parallel on your other machine. Phase 2 (Threshold DKG) is the next engineering
frontier when you're ready to pick it up.
noExplicitAny cleanup (PR #120)
- https://github.com/newt-foundation/newton-sdk/pull/120
- 10 files edited across types, utils, modules, and service layers
- Replaced any with proper types: unknown, WalletClient, PublicClient, PolicyParamsJson, JsonRpcRequestPayload, Record<string,
unknown> - Added biome-ignore comments for legitimate any usage: Promise API conformance (5), EventEmitter dynamic dispatch (6), type guards
(1) - Zero noExplicitAny warnings remain, TypeScript compiles clean, all 29 tests pass
NEWT-627 status: Already implemented in PR #115, status "In Review". No additional work needed — the client-side HPKE encryption
module is fully built and part of the stacked PR chain (#115→#116→#117) awaiting merge.
Phase 2 duplicate consolidation on Linear:
- NEWT-157 → marked as duplicate of NEWT-176 (threshold decryption), status set to Canceled
- NEWT-158 → marked as duplicate of NEWT-177 (DKG protocol), status set to Canceled
- Phase 2 goes from 8 issues to 6 active issues
- NEWT-176 and NEWT-177 are the canonical issues (they have Phase 2 milestone assignments and cross-references to
NEWT-628/NEWT-629)
★ Insight ─────────────────────────────────────
- The duplicates arose because NEWT-157/158 were created on Jan 18 as high-level "Phase 2" items with the Feature label, while
NEWT-176/177 were created the same day with detailed Rust implementation specs and milestone assignments — likely from two
different planning passes - Keeping the more detailed issues (NEWT-176/177) preserves the existing relatedTo connections to NEWT-628 (epoch key rotation) and
NEWT-629 (privacy slashing)
─────────────────────────────────────────────────
Newton Privacy Layer Phase 2: Threshold DKG — Research Synthesis
Executive Summary
Phase 2 replaces the gateway as sole decryptor with t-of-n threshold decryption across EigenLayer operators. The recommended architecture:
┌───────────────────────┬─────────────────────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────────────────┐
│ Decision │ Recommendation │ Rationale │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ DKG Protocol │ FROST DKG (RFC 9591) │ 2-round, production Rust crate (frost-ristretto255), no trusted dealer │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Curve │ Ristretto255 (not raw X25519) │ X25519 clamping breaks Shamir; Ristretto255 is cofactor-1 Curve25519 │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Threshold decryption │ Lagrange interpolation in the exponent │ Secret never reconstructed; KEM-layer only │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Consensus integration │ Option B: merge into Prepare phase │ Zero additional round trips │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Key rotation │ Proactive Secret Sharing (PSS) │ MPK unchanged across epochs; zero client UX impact │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ Slashing │ DLEQ fraud proofs (wrong-keyshare) + liveness attestation (no-keyshare) │ Cryptographically verifiable; ~40k gas on-chain │
├───────────────────────┼─────────────────────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────────────────┤
│ On-chain commitments │ Merkle root of partial decryptions + BLS co-signature │ Per-task 32-byte commitment; individual shares on EigenDA │
└───────────────────────┴─────────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────────────────┘
★ Insight ─────────────────────────────────────
- X25519 clamping is a showstopper — RFC 7748 mandates scalar clamping which is non-linear, breaking Shamir recombination. Ristretto255 (same underlying curve, prime-order
group, no clamping) is the correct DKG group. Conversion via EdwardsPoint::to_montgomery() preserves HPKE compatibility. - The gateway remains an untrusted combiner — it verifies DLEQ proofs and combines partial DH outputs but never holds shares. Trust level improves from "gateway sees all
plaintext always" to "gateway sees plaintext only during task processing, verified by operator co-attestation." - Threshold applies only at the KEM layer — HKDF and ChaCha20-Poly1305 run unchanged after threshold combining reconstructs the DH shared secret.
─────────────────────────────────────────────────
Architecture: Current → Phase 2
flowchart LR
subgraph PHASE1["Phase 1.5 (Current)"]
C1[Client] -->|HPKE encrypt to gateway key| GW1[Gateway]
GW1 -->|decrypt centrally| P1[Plaintext]
P1 -->|pass via ConsensusCommitRequest| O1[Operators]
end
subgraph PHASE2["Phase 2 (Target)"]
C2[Client] -->|HPKE encrypt to threshold MPK| GW2[Gateway]
GW2 -->|distribute enc to operators| O2[Operators]
O2 -->|partial DH + DLEQ proof| GW2
GW2 -->|Lagrange combine >= t shares| P2[Plaintext]
P2 -->|pass via ConsensusCommitRequest| O2
end
DKG Protocol Selection: FROST on Ristretto255
Why FROST
┌─────────────────────┬─────────────────────────────────┬───────────────────────────┬──────────────────────────────────┬───────────┐
│ Factor │ FROST │ Pedersen │ Joint-Feldman │ GJKR07 │
├─────────────────────┼─────────────────────────────────┼───────────────────────────┼──────────────────────────────────┼───────────┤
│ Rounds │ 2 │ 3 │ 3 │ 4 │
├─────────────────────┼─────────────────────────────────┼───────────────────────────┼──────────────────────────────────┼───────────┤
│ Rust crate │ frost-ristretto255 (production) │ vsss-rs (primitives only) │ None │ None │
├─────────────────────┼─────────────────────────────────┼───────────────────────────┼──────────────────────────────────┼───────────┤
│ Rushing adversary │ Proof-of-knowledge in R1 │ Not addressed │ Vulnerable (negligible for HPKE) │ Fixed │
├─────────────────────┼─────────────────────────────────┼───────────────────────────┼──────────────────────────────────┼───────────┤
│ Ristretto255 native │ Yes │ Any group │ Any group │ Any group │
└─────────────────────┴─────────────────────────────────┴───────────────────────────┴──────────────────────────────────┴───────────┘
DKG Ceremony Flow
sequenceDiagram
participant GW as Gateway (Coordinator)
participant O1 as Operator 1
participant O2 as Operator 2
participant On as Operator n
participant CH as On-Chain
Note over GW: Triggered by OperatorAdded/Removed event
rect rgb(230, 245, 255)
Note over O1,On: Round 1 — Commitments + Proof-of-Knowledge
O1->>GW: (C₁, PoK₁)
O2->>GW: (C₂, PoK₂)
On->>GW: (Cₙ, PoKₙ)
GW->>GW: Verify all PoKs, broadcast commitments
end
rect rgb(255, 245, 230)
Note over O1,On: Round 2 — Encrypted Share Distribution
O1->>O2: E(s₁₂) encrypted to O2's X25519 key
O1->>On: E(s₁ₙ) encrypted to On's X25519 key
O2->>O1: E(s₂₁)
On->>O1: E(sₙ₁)
Note over O1,On: Each operator verifies shares against commitments
end
O1->>CH: BLS-signed MPK commitment
O2->>CH: BLS-signed MPK commitment
Note over CH: Store threshold MPK in EpochRegistry
Curve Compatibility
DKG output: (sᵢ, MPK) on Ristretto255
HPKE encrypt: pk_hpke = MPK.to_montgomery() → standard X25519 point
Partial decrypt: Dᵢ = sᵢ * enc_ristretto → Ristretto255 scalar mult
Combine: D = Σ λᵢDᵢ (Lagrange) → shared_secret = D.to_montgomery()
KDF + AEAD: unchanged from Phase 1.5
Rust Crate Stack
┌─────────────────────────┬───────────────────────────────┬─────────────────────────────────────────────┐
│ Component │ Crate │ Notes │
├─────────────────────────┼───────────────────────────────┼─────────────────────────────────────────────┤
│ Ristretto255 arithmetic │ curve25519-dalek v4 │ Already transitive dep │
├─────────────────────────┼───────────────────────────────┼─────────────────────────────────────────────┤
│ Feldman VSS shares │ vsss-rs v4 │ New dep, Ristretto255 support │
├─────────────────────────┼───────────────────────────────┼─────────────────────────────────────────────┤
│ Full DKG ceremony │ frost-ristretto255 v2 │ New dep (ZCash Foundation) │
├─────────────────────────┼───────────────────────────────┼─────────────────────────────────────────────┤
│ DLEQ proofs │ ~50 lines on curve25519-dalek │ Custom, straightforward │
├─────────────────────────┼───────────────────────────────┼─────────────────────────────────────────────┤
│ HPKE after combining │ Existing hpke crate │ Needs open_with_precomputed_dh augmentation │
└─────────────────────────┴───────────────────────────────┴─────────────────────────────────────────────┘
Consensus Integration: Merged Prepare Phase (Option B)
sequenceDiagram
participant C as Client
participant GW as Gateway
participant O as Operators (1..n)
participant CH as On-Chain
Note over C,GW: UPLOAD (before task)
C->>GW: SecureEnvelope encrypted to MPK
GW->>GW: Store in encrypted_data_refs
rect rgb(230, 255, 230)
Note over GW,O: PREPARE PHASE (extended)
GW->>O: newt_fetchPolicyData + enc handles
O->>O: Fetch policyTaskData (existing)
O->>O: Compute Dᵢ = sᵢ * enc, DLEQ πᵢ (NEW)
O->>GW: {policyTaskData, Dᵢ, πᵢ}
end
rect rgb(255, 230, 230)
Note over GW: DECRYPTION + CONSENSUS
GW->>GW: Verify t DLEQ proofs
GW->>GW: Lagrange interpolate → plaintext
GW->>GW: Median consensus on policyTaskData
end
rect rgb(230, 230, 255)
Note over GW,O: COMMIT PHASE (unchanged)
GW->>O: ConsensusCommitRequest {consensus data + privacy_data}
O->>O: Evaluate policy + BLS sign
O->>GW: ConsensusCommitResponse
end
GW->>CH: respondToTask (BLS aggregated)
Latency impact: Operator computes Dᵢ (~0.3ms) alongside policyTaskData fetch — no additional round trip. Total crypto overhead: ~2.1ms for t=7, n=10.
Epoch-Based Key Rotation
Recommended Model: Proactive Secret Sharing (PSS)
┌──────────────────┬──────────────────────────┬───────────────────────┬─────────────────────┐
│ Property │ Full Rotation (Model A) │ PSS (Model B) │ Hybrid (Model C) │
├──────────────────┼──────────────────────────┼───────────────────────┼─────────────────────┤
│ Client UX change │ Yes (new MPK each epoch) │ No (MPK constant) │ Per long epoch │
├──────────────────┼──────────────────────────┼───────────────────────┼─────────────────────┤
│ Forward secrecy │ Full │ Mobile adversary only │ Full per long epoch │
├──────────────────┼──────────────────────────┼───────────────────────┼─────────────────────┤
│ DKG overhead │ Full DKG each epoch │ O(n²) refresh msgs │ Mixed │
├──────────────────┼──────────────────────────┼───────────────────────┼─────────────────────┤
│ Recommended for │ Phase 3 │ Phase 2 │ Phase 4 │
└──────────────────┴──────────────────────────┴───────────────────────┴─────────────────────┘
Epoch Lifecycle
EPOCH N EPOCH N+1
┌──────────────────────────────────────────────────┐
│ Share Refresh → Active → Grace Period → Destroy │ → Share Refresh
└──────────────────────────────────────────────────┘
↑ ↑
O(n²) proactive Destruction
share refresh attestation
(MPK unchanged) submitted on-chain
Defaults: Epoch = 7200 blocks (~24h), Overlap = 600 blocks (~2h), Grace = 300 blocks (~1h)
On-Chain: EpochRegistry Contract
contract EpochRegistry {
struct EpochCommitment {
uint256 epoch;
uint32 startBlock;
uint32 endBlock;
bytes32 mpk; // Ristretto255 threshold public key
bytes32 operatorSetFingerprint; // keccak256(sorted operators + weights)
uint16 threshold; // t
uint16 committeeSize; // n
bytes32[] operatorKeyshareCommitments; // g^{sᵢ} per operator
}
function triggerEpochRotation(EpochCommitment calldata) external;
function attestKeyshareDestroyed(uint256 epoch, bytes calldata sig) external;
event EpochRotated(uint256 indexed oldEpoch, uint256 indexed newEpoch);
}
Privacy-Specific Slashing
Violation Categories
┌──────────────────────┬─────────────────────────────────┬───────────────────────────────┬─────────┬───────────────────┐
│ Violation │ Detection │ Proof Type │ Slash % │ Phase │
├──────────────────────┼─────────────────────────────────┼───────────────────────────────┼─────────┼───────────────────┤
│ Wrong-keyshare │ DLEQ verification failure │ Cryptographic (deterministic) │ 10% │ Phase 2 │
├──────────────────────┼─────────────────────────────────┼───────────────────────────────┼─────────┼───────────────────┤
│ No-keyshare │ Operator absent from t shares │ Quorum attestation │ 1-2% │ Phase 2 │
├──────────────────────┼─────────────────────────────────┼───────────────────────────────┼─────────┼───────────────────┤
│ Premature decryption │ Unauthorized task participation │ On-chain authorization check │ 10% │ Phase 2 (partial) │
├──────────────────────┼─────────────────────────────────┼───────────────────────────────┼─────────┼───────────────────┤
│ Keyshare leakage │ Undetectable without TEE │ N/A │ N/A │ Phase 3 (TEE) │
└──────────────────────┴─────────────────────────────────┴───────────────────────────────┴─────────┴───────────────────┘
DLEQ Proof for Wrong-Keyshare Detection
Each partial decryption Dᵢ = sᵢ * enc comes with a DLEQ proof proving log_G(PKᵢ) == log_{enc}(Dᵢ). On-chain verification costs ~40k gas (2 BN254 scalar mults via EIP-196
precompiles).
New Contract: PrivacySlasher
PrivacySlasher.slashForInvalidKeyshare(operator, taskId, Dᵢ, πᵢ) // DLEQ fails → instant slash
PrivacySlasher.slashForLivenessViolation(operator, taskId, epoch, witnessSignatures) // absent → slash
Both call into EigenLayer's InstantSlasher.fulfillSlashingRequest().
On-Chain Commitments for Auditability
Three-Layer Commitment Scheme
flowchart TB
L1["Layer 1: DecryptionAuthorization
taskId + envelopeCommitment + policyClient + committeeId"]
L2["Layer 2: Share Merkle Root
keccak256(D₁,π₁ || D₂,π₂ || ... || Dₜ,πₜ)
Individual shares → EigenDA"]
L3["Layer 3: Reconstructed Commitment
Included in BLS consensus digest
Operators co-attest via BLS signature"]
L1 --> L2
L2 --> L3
Gas cost: ~23k per task (1 event emit + 1 mapping write). Individual share data goes to EigenDA, not L1 storage.
Codebase Integration Summary
Files That Change
┌─────────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
│ File │ Change │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/core/src/crypto/hpke.rs │ Add open_with_precomputed_dh() │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/core/src/crypto/envelope.rs │ Add decrypt_envelopes_threshold() │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/core/src/dkg/ (new) │ keyshare.rs, dleq.rs, threshold.rs │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/aggregator/src/rpc_server.rs │ Add partial_decryption + dleq_proof to ConsensusPrepareResponse │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/operator/src/config.rs │ Add DkgConfig │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/operator/src/builder.rs │ Load keyshare, register newt_partialDecrypt │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/operator/src/core.rs │ newt_partialDecrypt handler │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/gateway/src/rpc/api/sync.rs │ Replace decrypt_privacy_data() with threshold path │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/gateway/src/handler/mod.rs │ Threshold MPK instead of ECDSA-derived key │
├─────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ crates/gateway/src/dkg/ (new) │ coordinator.rs, aggregator.rs │
└─────────────────────────────────────┴─────────────────────────────────────────────────────────────────┘
Files That Do NOT Change
- crates/aggregator/src/bls.rs — BLS aggregation untouched
- crates/chain-watcher/ — operator set events already emitted correctly
- Client API schema — newt_getPrivacyPublicKey, newt_uploadEncryptedData unchanged
- SecureEnvelope wire format — same HPKE Base mode, different recipient key
Implementation Roadmap
Dependency Graph
flowchart TD
A["NEWT-177
FROST DKG Protocol
(frost-ristretto255)"]
B["NEWT-176
Threshold Decryption
(partial DH + DLEQ + Lagrange)"]
C["NEWT-628
Epoch Registry Contract
+ PSS Rotation"]
D["NEWT-178
Two-Phase Consensus
Integration (Option B)"]
E["NEWT-630
On-Chain Commitments
(Merkle root + BLS co-sig)"]
F["NEWT-629
Privacy Slashing
(DLEQ + liveness)"]
A --> B
B --> D
A --> C
C --> F
D --> E
E --> F
Phased Rollout
┌───────────────┬───────────────────────────────────────────────────────────────────────────┬──────────────────────────────┬───────────┐
│ Sub-Phase │ Scope │ Tickets │ Estimate │
├───────────────┼───────────────────────────────────────────────────────────────────────────┼──────────────────────────────┼───────────┤
│ 2A — MVP │ Trusted dealer (gateway runs Feldman VSS), threshold decrypt, DLEQ proofs │ NEWT-176, NEWT-177 (partial) │ 3-4 weeks │
├───────────────┼───────────────────────────────────────────────────────────────────────────┼──────────────────────────────┼───────────┤
│ 2B — Rotation │ PSS epoch refresh, EpochRegistry contract, destruction attestation │ NEWT-628, NEWT-174 │ 2-3 weeks │
├───────────────┼───────────────────────────────────────────────────────────────────────────┼──────────────────────────────┼───────────┤
│ 2C — Full DKG │ FROST ceremony (no trusted dealer), on-chain commitments │ NEWT-177 (full), NEWT-630 │ 2-3 weeks │
├───────────────┼───────────────────────────────────────────────────────────────────────────┼──────────────────────────────┼───────────┤
│ 2D — Slashing │ PrivacySlasher contract, DLEQ on-chain verification, liveness │ NEWT-629 │ 2 weeks │
└───────────────┴───────────────────────────────────────────────────────────────────────────┴──────────────────────────────┴───────────┘
Prerequisites
- hpke crate augmentation — need open_with_precomputed_dh (upstream PR or fork)
- frost-ristretto255 + vsss-rs — new Cargo dependencies (security audit required)
- Operator keyshare storage — encrypted keystore file (same pattern as BLS/ECDSA keys)
Fairblock Comparison — Final Assessment
┌────────────────────┬──────────────────────────────────┬──────────────────────────────────────────────┐
│ Dimension │ Newton Phase 2 │ Fairblock │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ DKG │ FROST (2-round, off-chain) │ Joint-Feldman (on-chain keyshare submission) │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ Encryption │ Threshold HPKE (Ristretto255) │ IBE (BLS12-381 pairings) │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ Share exchange │ Off-chain (P2P or via gateway) │ On-chain (x/keyshare module) │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ Key rotation │ PSS (constant MPK) │ Per-epoch new IBE master key │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ Slashing │ EigenLayer InstantSlasher + DLEQ │ Validator rewards (no slashing) │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ Decryption latency │ ~2.1ms crypto + network RTT │ ~28.5ms crypto (14x slower) │
├────────────────────┼──────────────────────────────────┼──────────────────────────────────────────────┤
│ Chain dependency │ Ethereum (EigenLayer) │ FairyRing (Cosmos) + IBC │
└────────────────────┴──────────────────────────────────┴──────────────────────────────────────────────┘
Adopted from Fairblock: epoch-based rotation model, MSK destruction pattern, privacy-specific slashing concept.
Not adopted: separate chain, on-chain keyshare aggregation, IBE, new token.
Known Limitations
- Gateway still reconstructs plaintext — threshold removes single-key custody but not single-point-of-reconstruction. Full MPC computation is Phase 3.
- X25519 → Ristretto255 KEM migration — DHKEM(Ristretto255) is in CFRG drafts only, not RFC 9180. Client libraries need updating.
- NATS infrastructure — the whitepaper specifies NATS for DKG ceremonies and share exchange, but NATS is not yet deployed. Phase 2A can use HTTP/JSON-RPC (existing operator
communication); NATS needed for Phase 2C. - Keyshare leakage undetectable — without TEE attestation, an operator leaking their keyshare is not provably slashable. Epoch rotation provides forward secrecy as mitigation.
- Centralized single-phase consensus — has no Prepare phase to piggyback partial decryptions on. Either needs a dedicated Phase 0 decrypt round or must be deprecated for
privacy-enabled tasks. - External cryptographic audit required — threshold HPKE with DLEQ proofs is custom cryptography. Independent review mandatory before mainnet deployment.
★ Insight ─────────────────────────────────────
- Phase 2A (MVP with trusted dealer) can ship in 3-4 weeks — the gateway already has the infrastructure to run Feldman VSS as a one-shot ceremony. This immediately eliminates
the "single static key" risk while the full FROST DKG is built. - The client API is unchanged — newt_getPrivacyPublicKey returns the threshold MPK instead of the gateway key. SecureEnvelope format identical. SDK migration is just pointing at
a different key. - PSS (Proactive Secret Sharing) is the key insight from Fairblock — it gives epoch-based forward secrecy without changing the public key, avoiding a client migration per epoch.
Newton should adopt this over Fairblock's "new IBE master key each epoch" approach.
─────────────────────────────────────────────────
Linear vs Research Sync Analysis
Here's what I found by comparing the 7 Linear tickets against docs/THRESHOLD_DKG.md:
Sync Issues Found
┌────────────────┬──────────────────────────────────────────────────────────────────────┬───────────────────────────────────────┐
│ Issue │ Problem │ Action Needed │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ NEWT-177 │ Describes Pedersen DKG (4 phases, ark-ec/blstrs), but research │ Update description to FROST │
│ │ recommends FROST DKG (2 rounds, frost-ristretto255) on Ristretto255 │ │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ NEWT-177 │ References G1Point/BLS12-381 types, not Ristretto255 │ Update types to Ristretto255 │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ NEWT-629 │ Labeled "[Privacy P3]" but belongs in Phase 2 sub-phase 2D │ Rename prefix to "[Privacy P2D]" │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ NEWT-630 │ Labeled "[Privacy P4]" but belongs in Phase 2 sub-phase 2C │ Rename prefix to "[Privacy P2C]" │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ All 4 original │ Due dates set to Feb 2026 (past) │ Clear or reset │
│ tickets │ │ │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ NEWT-628, 629, │ No assignee │ Assign to dennis.won │
│ 630 │ │ │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ Missing │ No ticket for HPKE crate augmentation (open_with_precomputed_dh) │ Create new ticket │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ Missing │ No ticket for DLEQ proof module │ Covered implicitly in NEWT-176 but │
│ │ │ deserves explicit sub-task │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ Missing │ No ticket for EpochRegistry contract │ Create new ticket under NEWT-628 │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ Missing │ No ticket for PrivacySlasher contract │ Create new ticket under NEWT-629 │
├────────────────┼──────────────────────────────────────────────────────────────────────┼───────────────────────────────────────┤
│ NEWT-174 vs │ │ NEWT-174 = Rust implementation; │
│ NEWT-628 │ Significant overlap (both describe PSS, epoch rotation) │ NEWT-628 = full spec including │
│ │ │ contract │
└────────────────┴──────────────────────────────────────────────────────────────────────┴───────────────────────────────────────┘
★ Insight ─────────────────────────────────────
Why FROST over Pedersen: The original Linear tickets were written before the research deep-dive. Pedersen DKG (NEWT-177's current
spec) has 3-4 rounds and requires a separate complaint/dispute phase. FROST DKG (RFC 9591) achieves the same security in 2 rounds
with built-in proof-of-knowledge, and has a production Rust crate (frost-ristretto255) from the ZCash Foundation. The X25519 clamping
issue (which breaks Shamir) makes Ristretto255 mandatory regardless of which DKG protocol we use.
─────────────────────────────────────────────────
Detailed Execution Plan
Sub-Phase 2A: MVP Threshold Decrypt (3-4 weeks)
Goal: Trusted dealer Feldman VSS, threshold decryption with DLEQ proofs, E2E test on local anvil.
Linear tickets: NEWT-177 (partial), NEWT-176
Week 1: Crypto Foundation
┌───────────────────────────────┬────────────────────────────────────┬──────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├───────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Add vsss-rs and │ crates/core/Cargo.toml │ Feature-gate behind privacy-threshold │
│ curve25519-dalek v4 deps │ │ │
├───────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Implement Feldman VSS dealer │ crates/core/src/dkg/keyshare.rs │ generate_shares(secret, threshold, n) -> Vec + │
│ │ (new) │ verification vector │
├───────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Implement DLEQ proofs │ crates/core/src/dkg/dleq.rs (new) │ prove(sk_i, enc_point) -> DleqProof, verify(pk_i, │
│ │ │ enc_point, D_i, proof) -> bool │
├───────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Ristretto255 <-> Montgomery │ crates/core/src/dkg/convert.rs │ ristretto_to_montgomery() for HPKE compatibility │
│ conversion │ (new) │ │
├───────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Unit tests for all crypto │ crates/core/src/dkg/mod.rs │ Round-trip VSS, DLEQ verification, conversion │
│ primitives │ │ correctness │
└───────────────────────────────┴────────────────────────────────────┴──────────────────────────────────────────────────────────┘
Week 2: HPKE Threshold Path
┌────────────────────────────────┬────────────────────────────────────┬──────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├────────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Fork/augment hpke crate │ crates/core/src/crypto/hpke.rs │ Add open_with_precomputed_dh(shared_secret, enc, ct, │
│ │ │ aad) that skips KEM │
├────────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Implement │ │ Accepts Vec<(OperatorId, PartialDecryption, DleqProof)>, │
│ decrypt_envelopes_threshold() │ crates/core/src/crypto/envelope.rs │ verifies proofs, Lagrange-interpolates, calls │
│ │ │ open_with_precomputed_dh │
├────────────────────────────────┼────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Threshold decryption │ crates/core/src/dkg/tests/ │ Encrypt with MPK.to_montgomery(), decrypt with t-of-n │
│ integration test │ │ partials │
└────────────────────────────────┴────────────────────────────────────┴──────────────────────────────────────────────────────────┘
Week 3: Operator + Gateway Integration
┌───────────────────────────────────────┬─────────────────────────────────────┬──────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├───────────────────────────────────────┼─────────────────────────────────────┼──────────────────────────────────────────────────┤
│ DkgConfig on operator │ crates/operator/src/config.rs │ keyshare_path, threshold, epoch_id │
├───────────────────────────────────────┼─────────────────────────────────────┼──────────────────────────────────────────────────┤
│ Keyshare loading at operator startup │ crates/operator/src/builder.rs │ Load from encrypted keystore file │
├───────────────────────────────────────┼─────────────────────────────────────┼──────────────────────────────────────────────────┤
│ newt_partialDecrypt RPC handler │ crates/operator/src/core.rs │ Compute D_i = s_i * enc_ristretto, generate DLEQ │
│ │ │ proof, return PartialDecryptionResponse │
├───────────────────────────────────────┼─────────────────────────────────────┼──────────────────────────────────────────────────┤
│ partial_decryption + dleq_proof on │ crates/aggregator/src/rpc_server.rs │ New optional fields │
│ ConsensusPrepareResponse │ │ │
├───────────────────────────────────────┼─────────────────────────────────────┼──────────────────────────────────────────────────┤
│ Gateway threshold decryption path │ crates/gateway/src/rpc/api/sync.rs │ In Prepare phase: collect partials, verify DLEQ, │
│ │ │ Lagrange-combine, decrypt │
├───────────────────────────────────────┼─────────────────────────────────────┼──────────────────────────────────────────────────┤
│ Threshold MPK on ChainService │ crates/gateway/src/handler/mod.rs │ Replace single HPKE key with epoch-aware MPK │
└───────────────────────────────────────┴─────────────────────────────────────┴──────────────────────────────────────────────────┘
Week 4: E2E Test + Polish
┌──────────────────────────────┬───────────────────────────────────────┬─────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├──────────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ Trusted dealer test fixture │ integration-tests/src/threshold.rs │ Generate VSS shares for N operators, distribute via │
│ generator │ (new) │ config files │
├──────────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ Threshold privacy E2E test │ integration-tests/tests/e2e.rs │ make e2e scenario=threshold-privacy — encrypt to MPK, 2 │
│ │ │ operators partial-decrypt, gateway combines │
├──────────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ newt_getPrivacyPublicKey │ crates/gateway/src/rpc/api/privacy.rs │ Epoch-aware: returns current epoch's MPK │
│ returns MPK │ │ │
├──────────────────────────────┼───────────────────────────────────────┼─────────────────────────────────────────────────────────┤
│ Metrics for threshold │ crates/metrics/src/lib.rs │ privacy_threshold_decrypt_duration, │
│ decryption │ │ privacy_dleq_verify_count │
└──────────────────────────────┴───────────────────────────────────────┴─────────────────────────────────────────────────────────┘
Exit criteria: Local anvil E2E passes with t=2, n=3 threshold decrypt using Feldman VSS dealer-generated shares.
Sub-Phase 2B: Epoch Rotation + PSS (2-3 weeks)
Goal: Epoch-based key rotation via PSS, EpochRegistry contract, old share destruction attestation.
Linear tickets: NEWT-628, NEWT-174
Week 5: PSS Protocol
┌───────────────────────────┬─────────────────────────────────────┬─────────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├───────────────────────────┼─────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
│ PSS refresh protocol │ crates/core/src/dkg/pss.rs (new) │ Each operator generates zero-secret polynomial, │
│ │ │ redistributes shares │
├───────────────────────────┼─────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
│ EpochMetadata types │ crates/core/src/dkg/epoch.rs (new) │ EpochMetadata, `EpochStatus::Active │
├───────────────────────────┼─────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
│ Epoch-aware keyshare │ crates/operator/src/keystore.rs │ Store multiple epoch shares, zeroize expired shares via │
│ storage │ (new) │ zeroize crate │
├───────────────────────────┼─────────────────────────────────────┼─────────────────────────────────────────────────────────────┤
│ Destruction attestation │ crates/operator/src/core.rs │ Ed25519-sign (epoch_id, "destroyed"), submit to gateway │
└───────────────────────────┴─────────────────────────────────────┴─────────────────────────────────────────────────────────────┘
Week 6: EpochRegistry Contract
┌──────────────────────────┬─────────────────────────────────────────┬───────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├──────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
│ │ contracts/src/core/EpochRegistry.sol │ registerEpoch(epochId, mpk, operatorSetHash, threshold), │
│ EpochRegistry.sol │ (new) │ getCurrentEpoch(), recordDestruction(epochId, │
│ │ │ operatorSig) │
├──────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
│ Forge tests for │ contracts/test/EpochRegistry.t.sol │ Epoch transitions, grace period expiry, destruction │
│ EpochRegistry │ (new) │ recording │
├──────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
│ Rust bindings + make │ crates/core/src/generated/ │ Auto-generated │
│ generate-bindings │ │ │
├──────────────────────────┼─────────────────────────────────────────┼───────────────────────────────────────────────────────────┤
│ Gateway epoch │ crates/gateway/src/dkg/coordinator.rs │ Trigger rotation at epoch boundary (block-based), │
│ coordinator │ (new) │ orchestrate PSS, publish MPK │
└──────────────────────────┴─────────────────────────────────────────┴───────────────────────────────────────────────────────────┘
Week 7: Integration + E2E
┌──────────────────────────────┬───────────────────────────────────────┬────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├──────────────────────────────┼───────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ │ integration-tests/tests/epoch.rs │ Rotate 3 epochs, verify: old shares zeroed, new MPK │
│ Epoch rotation E2E test │ (new) │ works, grace period decryption works, expired epoch │
│ │ │ fails │
├──────────────────────────────┼───────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ newt_getPrivacyPublicKey │ crates/gateway/src/rpc/api/privacy.rs │ Return {mpk, epoch_id, expires_at_block} │
│ epoch-aware │ │ │
├──────────────────────────────┼───────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ Emergency rotation admin │ crates/cli/src/commands/ │ make admin command=rotate_epoch │
│ command │ │ │
└──────────────────────────────┴───────────────────────────────────────┴────────────────────────────────────────────────────────┘
Exit criteria: Epoch rotation works on local anvil. Old epoch shares zeroed. Grace period decryption verified. Forward secrecy
integration test passes.
Sub-Phase 2C: Full FROST DKG + On-Chain Commitments (2-3 weeks)
Goal: Replace trusted dealer with trustless FROST DKG ceremony. Add on-chain decryption commitments.
Linear tickets: NEWT-177 (full), NEWT-630
Week 8-9: FROST DKG Ceremony
┌────────────────────────────────────┬───────────────────────────────────────┬───────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├────────────────────────────────────┼───────────────────────────────────────┼───────────────────────────────────────────────────┤
│ Add frost-ristretto255 dep │ crates/core/Cargo.toml │ Feature-gate behind frost-dkg │
├────────────────────────────────────┼───────────────────────────────────────┼───────────────────────────────────────────────────┤
│ FROST Round 1 (commitments + PoK) │ crates/core/src/dkg/frost.rs (new) │ Wraps frost-ristretto255 API │
├────────────────────────────────────┼───────────────────────────────────────┼───────────────────────────────────────────────────┤
│ FROST Round 2 (share distribution) │ crates/core/src/dkg/frost.rs │ Encrypted share delivery via existing HPKE │
├────────────────────────────────────┼───────────────────────────────────────┼───────────────────────────────────────────────────┤
│ DKG ceremony coordinator service │ crates/gateway/src/dkg/coordinator.rs │ Orchestrate 2-round ceremony across operators via │
│ │ │ HTTP/JSON-RPC │
├────────────────────────────────────┼───────────────────────────────────────┼───────────────────────────────────────────────────┤
│ Operator DKG participation handler │ crates/operator/src/builder.rs │ newt_dkgRound1, newt_dkgRound2 RPC handlers │
├────────────────────────────────────┼───────────────────────────────────────┼───────────────────────────────────────────────────┤
│ DKG ceremony trigger on operator │ crates/gateway/src/handler/mod.rs │ Listen for OperatorAddedToOperatorSet events │
│ set change │ │ │
└────────────────────────────────────┴───────────────────────────────────────┴───────────────────────────────────────────────────┘
Week 9-10: On-Chain Commitments
┌────────────────────────────────────┬────────────────────────────────────────────────┬──────────────────────────────────────────┐
│ Task │ Files │ Details │
├────────────────────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────┤
│ DecryptionCommitment type │ crates/core/src/dkg/commitment.rs (new) │ compute(epoch_id, task_id, partials, │
│ │ │ result) -> H256 │
├────────────────────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────┤
│ Add decryption_commitment to │ contracts/src/core/NewtonProverTaskManager.sol │ New bytes32 field in response struct │
│ TaskResponseMetadata │ │ │
├────────────────────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────┤
│ Gateway emits commitment on-chain │ crates/gateway/src/rpc/api/sync.rs │ Compute commitment alongside BLS │
│ │ │ aggregation │
├────────────────────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────┤
│ Share Merkle root for EigenDA │ crates/core/src/dkg/commitment.rs │ Merkle tree of (operatorId, D_i, pi_i) │
│ │ │ tuples │
├────────────────────────────────────┼────────────────────────────────────────────────┼──────────────────────────────────────────┤
│ Challenger decryption verification │ crates/challenger/src/lib.rs │ challengeDecryptionAggregation path │
└────────────────────────────────────┴────────────────────────────────────────────────┴──────────────────────────────────────────┘
Exit criteria: FROST DKG ceremony completes with 5 operators on local anvil. On-chain commitment stored and verifiable.
Sub-Phase 2D: Privacy Slashing (2 weeks)
Goal: Implement PrivacySlasher contract and off-chain detection for wrong-keyshare and no-keyshare violations.
Linear tickets: NEWT-629
Week 11: PrivacySlasher Contract
┌─────────────────────────┬───────────────────────────────────────────┬──────────────────────────────────────────────────────────┐
│ Task │ Files │ Details │
├─────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ │ contracts/src/core/PrivacySlasher.sol │ reportMissedPartialDecryption(operator, epochId, │
│ PrivacySlasher.sol │ (new) │ taskId), reportInvalidPartialDecryption(operator, │
│ │ │ partial, dleqProof) │
├─────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ DLEQ on-chain │ contracts/src/libraries/DleqVerifier.sol │ Verify DLEQ proofs using EIP-196 precompiles (~40k gas) │
│ verification │ (new) │ │
├─────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Integration with │ │ │
│ EigenLayer │ contracts/src/core/PrivacySlasher.sol │ fulfillSlashingRequest() call │
│ InstantSlasher │ │ │
├─────────────────────────┼───────────────────────────────────────────┼──────────────────────────────────────────────────────────┤
│ Forge tests │ contracts/test/PrivacySlasher.t.sol (new) │ Invalid partial -> slash, missed deadline -> slash, │
│ │ │ duplicate report -> revert │
└─────────────────────────┴───────────────────────────────────────────┴──────────────────────────────────────────────────────────┘
Week 12: Off-Chain Detection + E2E
┌─────────────────────────────────┬────────────────────────────────────────────────┬─────────────────────────────────────────────┐
│ Task │ Files │ Details │
├─────────────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ PartialDecryptionTracker │ crates/gateway/src/dkg/tracker.rs (new) │ Track requested vs received partials, │
│ │ │ detect timeouts │
├─────────────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ Gateway reports missed/invalid │ crates/chainio/src/avs/writer.rs │ report_missed_partial(), │
│ partials │ │ report_invalid_partial() │
├─────────────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ Slashing E2E test │ integration-tests/tests/privacy_slashing.rs │ Simulate operator submitting invalid DLEQ │
│ │ (new) │ proof, verify slash │
├─────────────────────────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────┤
│ Dispute window integration │ contracts/src/core/PrivacySlasher.sol │ 100-block window consistent with existing │
│ │ │ challenger │
└─────────────────────────────────┴────────────────────────────────────────────────┴─────────────────────────────────────────────┘
Exit criteria: Invalid DLEQ proof triggers on-chain slash on local anvil. Missed deadline detection works.
Missing Linear Tickets
Based on the analysis, we need these new tickets:
┌────────────────────────┬──────────┬───────────┬────────────────────────────────────────────────────────────────────────────────┐
│ New Ticket │ Parent │ Sub-Phase │ Description │
├────────────────────────┼──────────┼───────────┼────────────────────────────────────────────────────────────────────────────────┤
│ HPKE crate │ NEWT-176 │ 2A │ Fork/augment hpke crate with open_with_precomputed_dh for threshold path │
│ augmentation │ │ │ │
├────────────────────────┼──────────┼───────────┼────────────────────────────────────────────────────────────────────────────────┤
│ EpochRegistry contract │ NEWT-628 │ 2B │ Solidity contract for epoch lifecycle, MPK publication, destruction │
│ │ │ │ attestation │
├────────────────────────┼──────────┼───────────┼────────────────────────────────────────────────────────────────────────────────┤
│ PrivacySlasher │ NEWT-629 │ 2D │ Solidity contract for privacy-specific slashing via EigenLayer │
│ contract │ │ │ │
├────────────────────────┼──────────┼───────────┼────────────────────────────────────────────────────────────────────────────────┤
│ DleqVerifier library │ NEWT-629 │ 2D │ Solidity library for on-chain DLEQ proof verification via EIP-196 │
└────────────────────────┴──────────┴───────────┴────────────────────────────────────────────────────────────────────────────────┘
Tickets That Need Updates
┌─────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Ticket │ Update Needed │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-177 │ Update description: Pedersen DKG -> FROST DKG (RFC 9591), ark-ec -> frost-ristretto255, G1Point -> │
│ │ RistrettoPoint, 4 phases -> 2 rounds │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-177 │ Clear stale due date (was Feb 7) │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-176 │ Clear stale due date (was Feb 10) │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-178 │ Clear stale due date (was Feb 13), update to reference FROST not Pedersen │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-174 │ Clear stale due date (was Feb 13) │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-629 │ Rename "[Privacy P3]" -> "[Privacy P2D]" to match sub-phase numbering │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-630 │ Rename "[Privacy P4]" -> "[Privacy P2C]" to match sub-phase numbering │
├─────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ NEWT-628, 629, │ Assign to dennis.won │
│ 630 │ │
└─────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
★ Insight ─────────────────────────────────────
Sub-phase dependencies matter: 2A (MVP) is the critical path — everything else builds on it. 2B (rotation) and 2C (full DKG) can
partially overlap because they modify different subsystems: 2B is operator keystore + EpochRegistry contract, while 2C is the DKG
ceremony coordinator + on-chain commitments. 2D (slashing) must wait for both because it verifies DLEQ proofs (from 2A) in an epoch
context (from 2B).
The hpke crate augmentation is the single biggest technical risk — the standard HPKE API doesn't expose a open_with_precomputed_dh
entry point. We either need an upstream PR to the hpke crate (uncertain timeline) or a minimal fork. This should be spiked in week 1.
─────────────────────────────────────────────────
⏺ Memory file updated. Here's what changed:
Phase 2 section completely rewritten to reflect the Linear sync:
- 11 tickets across 4 sub-phases (was 7 flat tickets with no structure)
- Architecture decisions summary (FROST over Pedersen, Ristretto255, merged Prepare phase)
- Per-sub-phase tables with due dates, blocking relationships, and exit criteria
- Dependency graph showing the critical path: NEWT-638 → NEWT-176 → NEWT-178 → NEWT-630 → NEWT-629
- 4 new tickets captured: NEWT-638 (HPKE augmentation), NEWT-639 (EpochRegistry), NEWT-640 (PrivacySlasher),
NEWT-641 (DleqVerifier) - Key files that change section (from THRESHOLD_DKG.md)
- Technical risk items section highlighting the HPKE crate augmentation as highest risk
Other updates:
- Phase summary row updated: "Pedersen DKG" → "FROST DKG", "0/7" → "0/11"
- PR #424 added to open PRs
- Date bumped to 2026-03-08
- Removed the separate "Linear Issue Status" table (redundant with per-phase tables)
★ Insight ─────────────────────────────────────
The memory file now serves as a single source of truth linking Linear tickets to the docs/THRESHOLD_DKG.md
research synthesis. The dependency graph makes the critical path clear — NEWT-638 (HPKE crate augmentation) is the
gating item for the entire Phase 2A MVP, since threshold decryption can't work without open_with_precomputed_dh.
This is why it was created as a separate ticket rather than bundled into NEWT-176.
─────────────────────────────────────────────────
✻ Crunched for 5m 40s
❯ /claude-supermemory:super-save phase 2 plan of newton privacy layer for threshold dkg research and implementation
⏺ Let me save this Phase 2 Threshold DKG plan to Supermemory.
⏺ Bash(node "/Users/denniswon/.claude/plugins/cache/supermemory-plugins/claude-supermemory/0.0.1/scripts/save-projec
t-memory.cjs" "[SAVE:denniswon:2026-03-09]…)
⎿ Project knowledge saved: newton-prover-avs
ID: 9cHSozFhnpr4V62M8z1tGQ
⏺ Saved to Supermemory (ID: 9cHSozFhnpr4V62M8z1tGQ). The Phase 2 Threshold DKG execution plan — architecture
decisions, 4 sub-phase timeline, all 11 Linear tickets, dependency graph, and technical risks — is now persisted
across sessions.
PR created: https://github.com/newt-foundation/newton-prover-avs/pull/426
★ Insight ─────────────────────────────────────
Threshold decryption integration architecture: The key design choice here is the fallback pattern — when threshold
prerequisites aren't met (no threshold_ctx, insufficient partials, deserialization failure), the gateway
seamlessly falls back to centralized HPKE decryption (Phase 1 behavior). This means the feature can be deployed
without breaking existing privacy flows. Operators without threshold key shares simply don't return
partial_decryption data, and the gateway handles this gracefully.
Wire type separation: The PartialDecryptionData (serde-friendly Vec fields) vs dkg::PartialDecryption (curve
point/scalar types) split is intentional — JSON-RPC can't natively serialize Edwards points, so the wire format
uses raw bytes with From/TryFrom conversions at the boundary. This keeps crypto types out of the network layer.
─────────────────────────────────────────────────
Here's a summary of what NEWT-178 now covers across the two commits:
┌──────────┬─────────┬───────────────────────────────────────────────────────────────────────────────────┐
│ Commit │ Layer │ What │
├──────────┼─────────┼───────────────────────────────────────────────────────────────────────────────────┤
│ b23496c1 │ Layer 1 │ Decouple privacy data from policyTaskData — separate privacy_data channel │
├──────────┼─────────┼───────────────────────────────────────────────────────────────────────────────────┤
│ a93aad57 │ Layer 2 │ Threshold decryption integration — operator partial DH + gateway Lagrange combine │
└──────────┴─────────┴───────────────────────────────────────────────────────────────────────────────────┘
Remaining for full Phase 2 completion (separate tickets):
- NEWT-630: E2E test for threshold privacy + two-phase consensus
- NEWT-629: Gateway threshold config loading from DKG ceremony output (Phase 2C)
- Phase 2B: PSS epoch rotation, EpochRegistry contract
- Phase 2C: FROST ceremony replacing trusted dealer
Current Status: Phase 2 Threshold DKG
Branch/PR Stack (bottom to top)
main
└── #421 privacy-data-flow-fix ← fix: privacy data via separate channel
└── #422 multichain-routing-e2e-options ← feat: two-phase + attestation E2E options
└── #423 unified-e2e-runner ← feat: unified E2E with scenario presets
└── #424 phase2-threshold-dkg-docs ← docs: THRESHOLD_DKG.md
└── threshold-dkg ← empty (merge point, no PR yet)
└── #425 threshold-dkg-phase2a ← NEWT-176: Feldman VSS + DLEQ primitives
└── #426 threshold-consensus-integration ← NEWT-178: Two-Phase Consensus wiring
What's Implemented (3 commits, 3 branches)
Commit: 9ecf60ba
Branch: threshold-dkg-phase2a (PR #425)
Linear Ticket: NEWT-176
What: DKG primitives: crates/core/src/dkg/ — Feldman VSS, DLEQ proofs, Lagrange interpolation,
threshold_decrypt(),
compute_partial_decryption(), ThresholdConfig, KeyShare, unit tests
────────────────────────────────────────
Commit: b23496c1
Branch: threshold-consensus-integration (PR #426)
Linear Ticket: NEWT-178 (Layer 1)
What: Decouple privacy data from policyTaskData — separate ConsensusCommitRequest.privacy_data channel
────────────────────────────────────────
Commit: a93aad57
Branch: threshold-consensus-integration (PR #426)
Linear Ticket: NEWT-178 (Layer 2)
What: Wire threshold decryption into Two-Phase Consensus: operator computes partial DH in Prepare, gateway
combines
via Lagrange + fallback to centralized
Linear Ticket Status
┌──────────┬───────────────────────────────────┬─────────────┬────────────────────────────────────────────────┐
│ Ticket │ Title │ Status │ Notes │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ │ HPKE crate augmentation — │ │ Implemented in │
│ NEWT-638 │ open_with_precomputed_dh │ Done │ crates/core/src/crypto/threshold.rs (post-DH │
│ │ │ │ pipeline) │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ NEWT-176 │ Threshold decryption (t-of-n) — │ In Review │ Core DKG primitives, feature-gated behind │
│ │ Feldman VSS + DLEQ │ (PR #425) │ threshold │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ NEWT-178 │ Threshold Decryption for │ In Review │ Operator + gateway wiring, fallback to │
│ │ Two-Phase Consensus │ (PR #426) │ centralized │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ NEWT-177 │ DKG protocol — FROST on │ Backlog │ Phase 2C — full FROST ceremony replacing │
│ │ Ristretto255 │ │ trusted dealer │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ NEWT-628 │ Epoch-based key rotation with PSS │ Backlog │ Phase 2B │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ NEWT-630 │ On-chain aggregation commitments │ Backlog │ Phase 2C — depends on NEWT-178 │
├──────────┼───────────────────────────────────┼─────────────┼────────────────────────────────────────────────┤
│ NEWT-629 │ Privacy-specific operator │ Backlog │ Phase 2D — depends on NEWT-630 + NEWT-628 │
│ │ slashing │ │ │
└──────────┴───────────────────────────────────┴─────────────┴────────────────────────────────────────────────┘
What's NOT Done Yet
Phase 2A remaining:
- E2E test for threshold privacy + two-phase consensus — verifies the full pipeline with a trusted dealer
distributing shares, operators computing partials, gateway combining - Gateway threshold config loading — threshold_ctx is hardcoded to None; needs to be populated from a config file
or DKG ceremony output - Operator non-RPC path — core.rs:fetch_policy_data() (non-two-phase operator flow) doesn't have enc_point +
key_share wiring yet
Phase 2B (Weeks 5-7): PSS epoch rotation, EpochRegistry contract, destruction attestation
Phase 2C (Weeks 8-10): Full FROST ceremony (replace trusted dealer), on-chain Merkle root commitments, EigenDA
share storage
Phase 2D (Weeks 11-12): PrivacySlasher contract, DleqVerifier library (EIP-196), liveness slashing
Dependency Graph — Progress Overlay
NEWT-638 ✅ → NEWT-176 🔄 → NEWT-178 🔄 → NEWT-630 ⬜ → NEWT-629 ⬜
NEWT-177 ⬜ ──────────────↗ ↗
NEWT-177 ⬜ → NEWT-628 ⬜ ─────────────────────────↗
✅ = Done, 🔄 = In Review, ⬜ = Backlog
Recommended Next Steps (in order)
- Get PRs #421 → #422 → #423 → #424 merged — these are the base of the stack and need to land on main before the
DKG PRs can merge - Write Phase 2A E2E test — trusted dealer distributes Feldman VSS shares to 3 operators, run threshold privacy +
two-phase consensus E2E, verify decryption works - Add gateway threshold config loading — load ThresholdDecryptionContext from a JSON config file (operator public
shares, threshold params) so the gateway can actually use threshold mode - Update Linear tickets — mark NEWT-638 as Done, move NEWT-176 and NEWT-178 to In Review
- Phase 2B kickoff — NEWT-628 (PSS rotation) and NEWT-639 (EpochRegistry contract) can start once 2A is merged
★ Insight ─────────────────────────────────────
Phase 2A is architecturally complete — all the crypto primitives (Feldman VSS, DLEQ proofs, Lagrange
interpolation) and the Two-Phase Consensus wiring (operator partial DH + gateway combine + fallback) are
implemented and compiling. What remains is operationalization: config loading, E2E testing, and getting the base
PR stack merged. The critical path blocker is the 6-PR stack depth — PRs #421-#424 need to land before the DKG
code can reach main.
The fallback pattern is key to safe rollout: even after deploying threshold code, the gateway falls back to
centralized HPKE decryption when threshold_ctx is None or insufficient partials arrive. This means threshold mode
can be enabled per-deployment without breaking existing privacy flows.
─────────────────────────────────────────────────
★ Insight ─────────────────────────────────────
Three fixes applied to get clean compilation:
- Vec → &[u8; 32] (line 194): hex::decode returns Vec, but montgomery_to_edwards expects a fixed-size
array reference. The .as_slice().try_into() pattern is idiomatic Rust for this conversion — TryFrom<&[u8]> for
&[u8; N] checks length at runtime and returns an error if it doesn't match. - Ambiguous AsRef (line 422): alloy::primitives::FixedBytes<32> (returned by keccak256) implements both
AsRef<[u8; 32]> and AsRef<[u8]>. hex::encode accepts AsRef<[u8]>, but the compiler can't choose between the two
AsRef impls. Using .as_slice() explicitly selects the &[u8] variant. - Dead imports: ed25519_to_x25519_public, reqwest::Client, serde_json::Value, and uuid::Uuid were imported but
unused. The test utilities use the privacy module's upload_encrypted_data (which owns the HTTP client internally)
rather than constructing one directly.
─────────────────────────────────────────────────
Here's a summary of everything delivered:
File: integration-tests/src/threshold.rs
Change: New — DKG ceremony, threshold envelope creation, smoke test, full E2E runner (~467 lines)
────────────────────────────────────────
File: integration-tests/tests/threshold_e2e.rs
Change: New — test harness on port 8086
────────────────────────────────────────
File: integration-tests/src/lib.rs
Change: Added pub mod threshold;
────────────────────────────────────────
File: integration-tests/Cargo.toml
Change: Added threshold feature to core/gateway/operator deps
────────────────────────────────────────
File: crates/gateway/tests/{send_task,secrets_encrypted,chain_routing,watcher_endpoint}.rs
Change: Added #[cfg(feature = "threshold")] threshold: None
────────────────────────────────────────
File: Makefile
Change: Added threshold-e2e target with TWO_PHASE_CONSENSUS=true PRIVACY_ENABLED=true
Run with: make threshold-e2e
★ Insight ─────────────────────────────────────
Threshold decryption and multichain routing are orthogonal concerns. Threshold is about who decrypts (centralized
gateway vs distributed operators). Multichain routing is about where tasks go (which chain's ChainService handles
the task). The threshold code path in sync.rs (extract_enc_point_for_threshold, try_threshold_decrypt) is
identical regardless of which chain the task targets — it operates on the ChainServiceCtx.threshold_ctx which is
cloned from the gateway-level config to every chain service.
─────────────────────────────────────────────────
My recommendation: skip integration into multichain-routing-e2e for now. Here's why:
- Config construction mismatch: multichain-routing-e2e uses MultichainRoutingConfig →
MultiChainConfig::from_network() → Gateway::from_multi_chain_config(). Injecting ThresholdGatewayConfig into that
pipeline requires modifying MultichainRoutingConfig and the MultiChainConfig builder — nontrivial plumbing for a
feature that's still Phase 2A. - Encryption target changes: Privacy in multichain-routing encrypts to the gateway's ECDSA-derived HPKE key.
Threshold encrypts to the DKG master public key. These are different keys with different derivation paths.
Supporting both in one test means conditional encryption logic and more config branching. - No new code path exercised: The threshold logic in sync.rs doesn't branch on chain_id or multichain mode. If
threshold works for chain 31337, it works identically for chain 31338 — the same threshold_ctx is shared across
all ChainService instances. - Phase 2C is the right time: When FROST DKG replaces the trusted dealer, the DKG ceremony itself becomes
multichain-aware (operators on different chains participate). That's when integrating into multichain-routing-e2e
makes architectural sense.
What threshold-e2e tests (the current spec)
The test runs two phases:
Phase A — In-process crypto smoke test (no infrastructure)
- Runs 2-of-3 Feldman VSS DKG ceremony
- Encrypts test data ({"kyc_verified": true, "risk_score": 42}) to the threshold MPK
- Computes 2 partial decryptions from shares 1 and 3 (any 2-of-3 subset)
- Combines via Lagrange interpolation and verifies decrypted plaintext matches original
- Validates the full crypto pipeline works correctly before touching any infrastructure
Phase B — Full E2E with gateway + operator (requires anvil + Postgres)
- Runs 1-of-1 DKG ceremony (single operator can satisfy threshold)
- Injects ThresholdGatewayConfig into gateway and ThresholdOperatorConfig into operator
- Starts operator with key share on port 127.0.0.1:9013
- Starts gateway on port 8086 with threshold decryption context
- Encrypts privacy data to threshold MPK (not gateway's centralized key)
- Uploads encrypted data via newt_uploadEncryptedData
- Computes dual Ed25519 signatures (user + app) for privacy authorization
- Submits task with encrypted_data_refs + use_two_phase = true
- Verifies: task succeeds, BLS aggregation response is valid
- During Prepare phase: operator receives enc_point, computes partial DH + DLEQ proof
- During Commit: gateway combines partials, decrypts privacy data, passes via ConsensusCommitRequest.privacy_data
Run with: make threshold-e2e
SDK Privacy PRs — Protocol Alignment Analysis
PR #115 (feature/sdk-privacy-module) — HPKE Encryption
┌────────────────────────────────────┬────────┬───────────────────────────────────────────────────────────────────────────────┐
│ Check │ Status │ Detail │
├────────────────────────────────────┼────────┼───────────────────────────────────────────────────────────────────────────────┤
│ HPKE suite │ Match │ Both: X25519 KEM + HKDF-SHA256 + ChaCha20-Poly1305, Base mode │
├────────────────────────────────────┼────────┼───────────────────────────────────────────────────────────────────────────────┤
│ HPKE info param │ Match │ Both pass empty bytes (&[] / new Uint8Array(0)) │
├────────────────────────────────────┼────────┼───────────────────────────────────────────────────────────────────────────────┤
│ AAD computation │ Match │ Both: keccak256(encodePacked(policy_client_bytes, chain_id_be_u64)), strip 0x │
│ │ │ prefix │
├────────────────────────────────────┼────────┼───────────────────────────────────────────────────────────────────────────────┤
│ SecureEnvelope fields │ Match │ Identical: enc, ciphertext, policy_client, chain_id, recipient_pubkey │
├────────────────────────────────────┼────────┼───────────────────────────────────────────────────────────────────────────────┤
│ UploadEncryptedDataRpcRequest │ Match │ All 7 fields match Rust's UploadEncryptedDataRequest including required │
│ fields │ │ chain_id │
├────────────────────────────────────┼────────┼───────────────────────────────────────────────────────────────────────────────┤
│ chain_id required (not optional) │ Match │ Both sides: required u64/number per PR #421 fix │
└────────────────────────────────────┴────────┴───────────────────────────────────────────────────────────────────────────────┘
★ Insight ─────────────────────────────────────
The AAD computation is the most critical interop point. If SDK and Rust compute different AAD, the gateway cannot decrypt what the
SDK encrypts. Both implementations: (1) strip 0x prefix from policy_client, (2) decode to raw address bytes (20 bytes), (3)
encode chain_id as big-endian u64 (8 bytes), (4) concatenate, (5) keccak256. The SDK uses DataView.setUint32 twice for the u64 to
avoid BigInt — clever and correct.
─────────────────────────────────────────────────
PR #116 (feature/sdk-privacy-apis) — Dual Signatures + Key Generation
┌───────────────────────────────────────┬────────────┬────────────────────────────────────────────────────────────────────────┐
│ Check │ Status │ Detail │
├───────────────────────────────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤
│ User message construction │ Match │ Both: encodePacked(policy_client, intent_hash, ref_id_1, ref_id_2, │
│ │ │ ...) where ref_ids are UTF-8 bytes │
├───────────────────────────────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤
│ App message construction │ Match │ Both: encodePacked(policy_client, intent_hash, user_signature_bytes) │
├───────────────────────────────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤
│ Digest computation │ Match │ Both: keccak256(message) then Ed25519 sign the 32-byte digest │
├───────────────────────────────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤
│ Ed25519 sign/verify │ Compatible │ Rust: ed25519_dalek, SDK: @noble/curves/ed25519 — both implement │
│ │ │ standard Ed25519 (RFC 8032) │
├───────────────────────────────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤
│ Key zeroing │ Match │ Both zeroize private key bytes after use │
├───────────────────────────────────────┼────────────┼────────────────────────────────────────────────────────────────────────┤
│ SubmitEvaluationRequestParams privacy │ Match │ encryptedDataRefs, userSignature, appSignature — all optional, │
│ fields │ │ matching Rust's CreateTaskRequest │
└───────────────────────────────────────┴────────────┴────────────────────────────────────────────────────────────────────────┘
PR #117 (feature/sdk-privacy-docs) — Documentation
┌─────────────────────────────────────┬─────────┬─────────────────────────────────────────────────────────────────────┐
│ Check │ Status │ Detail │
├─────────────────────────────────────┼─────────┼─────────────────────────────────────────────────────────────────────┤
│ Architecture diagram (README.md) │ Correct │ Shows gateway decrypts, broadcasts plaintext to operators │
├─────────────────────────────────────┼─────────┼─────────────────────────────────────────────────────────────────────┤
│ Signature scheme docs (concepts.md) │ Correct │ Accurately describes user + app dual-signature construction │
├─────────────────────────────────────┼─────────┼─────────────────────────────────────────────────────────────────────┤
│ AAD binding explanation │ Correct │ Correctly explains keccak256(encodePacked(policy_client, chain_id)) │
├─────────────────────────────────────┼─────────┼─────────────────────────────────────────────────────────────────────┤
│ Phase 1 limitations │ Correct │ Documents centralized gateway trust point, Phase 2 threshold DKG │
└─────────────────────────────────────┴─────────┴─────────────────────────────────────────────────────────────────────┘
Issues Found
- Stale doc: "merged into evaluation context" (PR #117, examples.md)
The last line of Example 4 in examples.md:
"The Rego policy receives all decrypted data merged into its evaluation context, so it can cross-reference identity and financial
information in a single evaluation pass."
After PR #421, privacy data is namespaced under data.data.privacy in the Rego context — it is NOT flat-merged into policyTaskData.
Data flows through the separate ConsensusCommitRequest.privacy_data channel. The statement should say something like: "The Rego
policy receives all decrypted data under data.data.privacy in the evaluation context."
Severity: Low — describes the internal data layout that SDK consumers don't directly control, but it could mislead Rego policy
authors about where to find privacy fields.
- recipient_pubkey naming confusion (both SDK and Rust)
In UploadEncryptedDataRequest/UploadEncryptedDataRpcRequest, the field recipient_pubkey actually receives the sender's
(uploader's) Ed25519 public key — used by the gateway to verify the envelope signature. The Rust doc comment says "Recipient
operator Ed25519 public key" which is inaccurate.
In the SDK: recipient_pubkey: senderPublicKey — the variable name makes the confusion explicit.
Meanwhile, SecureEnvelope.recipient_pubkey stores the gateway's X25519 key (the actual encryption recipient).
Two fields named recipient_pubkey meaning different things in different structs.
Severity: Low — functionally correct (SDK and Rust agree on what goes where), but naming is misleading. Should be renamed to
sender_pubkey or signer_pubkey on the upload request to distinguish from the envelope's recipient_pubkey. This should be a
coordinated rename across both repos.
- Missing user_pubkey/app_pubkey in CreateTaskRequest (known gap)
The Rust validate_privacy_signatures() requires user_pubkey: &[u8; 32] and app_pubkey: &[u8; 32], but:
- CreateTaskRequest only has user_signature and app_signature — no public key fields
- validate_privacy_signatures is not yet called from the task creation handler in sync.rs
- The SDK's SubmitEvaluationRequestParams also has no public key fields
When the gateway enforces signature validation (presumably before production launch), either:
- Both Rust CreateTaskRequest and SDK SubmitEvaluationRequestParams will need user_pubkey and app_pubkey fields added
- OR the gateway derives user_pubkey from the upload record's recipient_pubkey (stored during uploadEncryptedData) and adds
app_pubkey to the request only
The SDK already computes and returns both public keys from signPrivacyAuthorization() (userPublicKey, appPublicKey), so the data
is available — it just doesn't flow into the task submission request yet.
Severity: Medium — not broken today (validation isn't enforced), but will require a coordinated SDK + gateway change before
signature enforcement goes live. Track this.
- SendTaskRequest missing privacy fields (Rust side)
CreateTaskRequest (sync path) has encrypted_data_refs, user_signature, app_signature, but SendTaskRequest (async path, line 56 of
types/mod.rs) does NOT have these fields. Privacy-enabled tasks won't work through the async newt_sendTask endpoint.
Severity: Low for Phase 1 (privacy tasks use the sync path), but should be addressed when expanding privacy support to the async
path.
Summary
Phase 1 SDK-Protocol alignment is solid. The three critical interop points all match:
- HPKE encryption (suite, AAD, info, envelope format) — exact match
- Dual-signature scheme (message construction, digest, Ed25519 compat) — exact match
- RPC request types (UploadEncryptedDataRpcRequest, privacy fields on task creation) — exact match
The four issues found are all low-to-medium severity future work items, not blocking for Phase 1. The most actionable one is the
stale doc in examples.md (issue #1), which can be fixed in PR #117 before merge. The recipient_pubkey rename (issue #2) and
missing public keys for signature enforcement (issue #3) should be tracked as follow-up work.
★ Insight ─────────────────────────────────────
The SDK is slightly ahead of the gateway in one respect: it implements and returns the dual-signature public keys
(signPrivacyAuthorization returns userPublicKey and appPublicKey), but neither the gateway's CreateTaskRequest nor the SDK's
SubmitEvaluationRequestParams sends them. When the gateway wires validate_privacy_signatures into the task creation handler, both
sides need to add the pubkey fields — but the SDK already has the data ready.
─────────────────────────────────────────────────
Pushed 727f739. All deferred items are now done:
┌──────────────────────────────────┬───────────────────────────────────────────────────────────────────┬──────────────────────────────┐
│ Item │ Fix │ File │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ Privacy methods undocumented │ Added full section with 6 methods, signatures, params, examples │ sdk-reference.mdx │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ Privacy types missing │ Added 6 expandable type definitions │ sdk-reference.mdx │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ precomputePolicyId missing │ Added optional blockTimestamp?: bigint, made expireAfter optional │ sdk-reference.mdx │
│ params │ │ │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ any types in signatures │ Changed to unknown in evaluateIntentDirect and │ sdk-reference.mdx │
│ │ AggregationResponse │ │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ console.log leak │ Removed all 3 console statements, added no-op handlers │ task-events.ts │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ wasmArgs wrong level │ Removed invalid top-level wasmArgs from example │ frontend-sdk-integration.mdx │
├──────────────────────────────────┼───────────────────────────────────────────────────────────────────┼──────────────────────────────┤
│ Stale gateway URL in JSDoc │ Updated to gateway.testnet.newton.xyz │ task-events.ts │
└──────────────────────────────────┴───────────────────────────────────────────────────────────────────┴──────────────────────────────┘
Zero deferred items remaining.
Given your focus on security, privacy preservation, and performance/reliability, here's the prioritized execution order for these
lessons, filtered through Newton's compliance-first philosophy.
★ Insight ─────────────────────────────────────
The prioritization principle: anything that prevents plaintext leakage or improves system reliability gets done first. Product
expansion (stablecoins, precompiles) is deferred until the core privacy guarantee is airtight and performant.
─────────────────────────────────────────────────
Priority Execution Order
Tier 1: Security & Privacy Foundation (Do First — Phase 2 prerequisites)
P1. Client-side encryption SDK (Lesson 8) — NEWT-182
the entry point of the entire privacy guarantee.
encryption. SDK should work offline for the encryption step.
P2. Epoch-based key rotation with MSK destruction (Lesson 5) — NEWT-174/NEWT-189
Forward secrecy limits the blast radius of any compromise.
(DKG ceremony takes time). Start with longer epochs (24h), tune down.
P3. Validator slashing for privacy failures (Lesson 6)
plaintext. This is the enforcement mechanism for the privacy guarantee.
Tier 2: Performance & Reliability (Do Next — Phase 2 core)
P4. On-chain key aggregation verifiability (Lesson 4)
Off-chain aggregation in the Prepare Phase is fast but opaque. On-chain verification adds auditability without necessarily moving the
computation on-chain.
result) on-chain. Challengers can verify within a dispute window — mirrors Newton's existing challenger pattern.
P5. Batch decryption evaluation (Lesson 3)
(multiple envelopes in one task) become common, O(N×t) will become a bottleneck.
IBE-style batch decryption as a Phase 3 optimization.
it.
Tier 3: Strategic Expansion (Do Later — Phase 3+)
P6. Conditional decryption as complementary mode (Lesson 2)
It opens new markets (auctions, MEV protection) but doesn't strengthen the core privacy guarantee.
governance vote deadline. Keep it simple — don't try to match Fairblock's full condition expressiveness.
P7. Precompile-based EVM integration (Lesson 9)
privacy. SDK integration works fine for initial deployments.
P8. Confidential stablecoins / private amounts (Lesson 7)
ElGamal, range proofs) and a separate security audit. Pursue only after the core privacy layer is battle-tested.
Execution Summary
PHASE 2 PREREQUISITES (security + privacy foundation)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
P1 Client-side-only encryption (NEWT-182) ← entry point security
P2 Epoch key rotation + MSK destruction ← forward secrecy
P3 Privacy-specific operator slashing ← enforcement mechanism
PHASE 2 CORE (performance + reliability)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
P4 On-chain aggregation commitments ← auditability
P5 Batch decryption benchmarking ← measure, then optimize
PHASE 3+ (strategic expansion)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
P6 Conditional decryption mode ← new markets
P7 EVM precompiles ← distribution
P8 Confidential amounts ← new product
★ Insight ─────────────────────────────────────
The "skip centralized stepping stone" lesson (Lesson 1) is intentionally NOT in this list. Per your philosophy, Phase 1.5
gateway-mediated decryption is the correct stepping stone — it validates the full pipeline securely before distributing trust. The
priority is to make Phase 2 DKG as robust as possible when it ships, not to skip Phase 1.5. P1-P3 above are the foundation that makes
Phase 2 DKG trustworthy when it arrives.
Performance note on threshold decryption: The biggest reliability risk in Phase 2 is operator liveness during the Prepare Phase. If 1
of t operators is down, threshold decryption fails. Mitigation: set t < n with margin (e.g., 3-of-5 not 4-of-5), implement timeout +
fallback, and use P3 slashing to incentivize uptime.
─────────────────────────────────────────────────