Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion agent/flow-trace/00_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,14 @@ _Found during source-code cross-referencing of these trace documents._
| 9 | `_validateNodeEligibility` calls `bondingRegistry.getTicketBalanceAtBlock()` (not `ticketToken.getPastVotes()` directly). | CiphernodeRegistryOwnable.sol:668 | 03_E3_REQUEST |
| 10 | Lane A slashing uses **attestation-based** verification (committee quorum votes), not direct ZK proof re-verification on-chain. `proposeSlash()` decodes voter addresses, agrees, data hashes, and ECDSA signatures — not ZK proofs. | SlashingManager.sol | 05_FAILURE |

### Circuit Audit Remediations

| Finding | Status | Implemented behavior |
| ----------------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **IF-001 — unconstrained U64 modular division** | Fixed | `ModU64::div_mod` verifies the hinted quotient satisfies `result * divisor == dividend (mod modulus)`; the Noir suite includes a non-invertible-divisor regression test. |
| **IF-002 — conditional C7 decoding equality** | Fixed | C7 compares every decoded coefficient with the claimed message, including zero coefficients; a focused regression test rejects a nonzero decoded value claimed as zero. |
| **IF-003 — decryption proof phase and party binding** | Fixed | `decryption_aggregator` requires 1-indexed, strictly increasing party IDs, while `BfvDecryptionVerifier` checks the surfaced SK/ESM commitments against the E3's registry-backed DKG anchors. |

### Protocol Design Concerns

| # | Concern | Severity | Detail |
Expand Down Expand Up @@ -224,4 +232,4 @@ _Found during source-code cross-referencing of these trace documents._
| 31 | **Fault-attributed, token-aware failure settlement (AUD H-01)** | Resolved | `FailureReason` is exhaustively classified as requester-side or supplier/ciphernode-side. Requester/DP/CP failures pay completed work from the request-time fee allocation. Supplier/ciphernode failures return 100% of fee escrow with no protocol cut; honest nodes are compensated only from actual ticket slashes. Slash assets retain their ERC-20 denomination in independent pull claims, so no oracle conversion or relabeling occurs. Failure-triggering slash policies must expel the faulty operator before honest recipients are resolved. |
| 32 | **Proof-disabled publication bypass (AUD C-02)** | Fixed | E3 requests no longer carry a proof-aggregation switch and both final verifier calls are mandatory. Only binaries compiled with the `test-only-skip-proof-aggregation` Cargo feature can honor the ciphernode `skip_proof_aggregation` test/CI setting; production builds reject it. Feature-gated test nodes use non-empty C5/C7 placeholders accepted by mock deployments, while production verifiers reject those placeholders. |
| 33 | **Client public-key commitment binding (AUD C-01)** | Resolved | Serialized public-key event bytes are treated as an untrusted transport hint. Rust indexers decode the key and store it only when its recomputed circuit commitment equals the on-chain value; the TypeScript SDK exposes the event commitment and a semantic validator, which the default app runs before encryption. Calldata substitution therefore cannot become a different first-party client encryption key. The commitment itself is C5-proven by the mandatory final DKG proof. |
| 34 | **Cross-E3 decryption-proof replay (AUD C-03)** | Resolved | Every secret-bearing C6 proof commits to a domain over `(chainId, Interfold address, e3Id, committeeHash, ciphertextOutputHash, committeePublicKey)`. C6 folding requires one common domain, the final DecryptionAggregator proof exposes it, and the BFV wrapper rejects any domain that differs from the value recomputed by `Interfold`. This prevents cross-chain, cross-deployment, cross-E3, cross-committee, cross-ciphertext, and cross-key replay without a global consumed-proof storage ledger. |
| 34 | **Cross-E3 decryption-proof replay (AUD C-03)** | Resolved | Every secret-bearing C6 proof commits to a domain over `(chainId, Interfold address, e3Id, committeeHash, ciphertextOutputHash, committeePublicKey)`. C6 folding requires one common domain, the final DecryptionAggregator proof exposes it, and the BFV wrapper rejects any domain that differs from the value recomputed by `Interfold`. The wrapper also receives `e3Id` separately and checks each proof party's SK/ESM commitments against the registry's stored DKG anchors. This prevents cross-chain, cross-deployment, cross-E3, cross-committee, cross-ciphertext, and cross-key replay without a global consumed-proof storage ledger. |
20 changes: 17 additions & 3 deletions agent/flow-trace/04_DKG_AND_COMPUTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,8 @@ ShareVerificationActor receives ShareVerificationDispatched(kind=ShareProofs)
│ │ │ C4a→C6 (SameParty): C4a's commitment == C6's expected_sk_commitment
│ │ │ C4b→C6 (SameParty): C4b's commitment == C6's expected_e_sm_commitment
│ │ │ C6→C7 (CrossParty): C6's d_commitment matches C7's expected_d_commitment
│ │ │ (on-chain / E3 state) C3 `ct_commitment` output and C6 `ct_commitment` input bind to the same ciphertext as user_data_encryption (not a CommitmentLink row)
│ │ │ (on-chain / E3 state) C3/C6 ciphertext commitments are checked against their ciphertext witnesses off-chain;
│ │ │ the final EVM proof does not yet expose a ciphertext commitment for comparison with `keccak256(e3.ciphertextOutput)`
│ │ │
│ │ ├─ On mismatch: publishes CommitmentConsistencyViolation
│ │ │ → AccusationManager initiates accusation quorum (see Part 5)
Expand Down Expand Up @@ -702,6 +703,15 @@ on-chain; the explicit test/CI skip mode works only with mock verifiers that tru
> zero/EOA circuit-verifier addresses and zero recursive VK hashes. Production deployment tooling
> additionally compares the immutable VK hashes with the version-controlled circuit artifacts.

The decryption wrapper exposes
`verify(e3Id, decryptionDomain, plaintextOutputHash, committeeHash, proof)`. `Interfold` recomputes
`decryptionDomain` over
`(chainId, Interfold address, e3Id, committeeHash, ciphertextOutputHash, committeePublicKey)`. The
wrapper checks the domain limbs in the final proof, then uses the separate `e3Id` to resolve the
registry's stored DKG anchors and compares every surfaced party ID, secret-key commitment, and
smudging-noise commitment. The party IDs are circuit-side 1-indexed Shamir coordinates and are
translated to the registry's 0-indexed committee slots for this comparison.

---

## Phase 3: Encrypted Computation
Expand Down Expand Up @@ -896,6 +906,8 @@ InterfoldSolReader decodes CiphertextOutputPublished event
│ │ │ inside `DecryptionAggregator`
│ │ ├─ `DecryptionAggregator` exposes that C6-authenticated domain as two public
│ │ │ 128-bit limbs in the final EVM proof
│ │ ├─ `DecryptionAggregator` requires 1-indexed, strictly increasing party IDs;
│ │ │ zero, out-of-range, and duplicate reconstruction slots are rejected
│ │ ├─ Tracks the in-flight correlation id
│ │ ├─ ComputeRequestError, missing C6 inner proofs, or C7/decryption-aggregator proof-count
│ │ │ mismatches now emit
Expand Down Expand Up @@ -927,12 +939,14 @@ InterfoldSolReader decodes CiphertextOutputPublished event
│ │ committeeHash, ciphertextOutput, │
│ │ committeePublicKey │
│ │ )), then call decryptionVerifier.verify( │
│ │ decryptionDomain, keccak256(output),
│ │ e3Id, decryptionDomain, keccak256(output), │
│ │ committeeHash, proof │
│ │ ) │
│ │ → C-03: final proof domain must match the │
│ │ domain already committed by every C6 leaf. │
│ │ → M-34: c6Fold / C7 VK hashes are immutable. │
│ │ → IF-003: e3Id resolves stored DKG anchors; │
│ │ │ proof party IDs and SK/ESM commitments match.│
│ │ → M-34: c6Fold / C7 VK hashes are immutable. │
│ │ → M-35: revert path only (no `bool false`). │
│ │ 4. stage = Complete │
│ │ 5. _distributeRewards(e3Id) │
Expand Down
12 changes: 6 additions & 6 deletions agent/flow-trace/06_DEACTIVATION_AND_COMPLETION.md
Original file line number Diff line number Diff line change
Expand Up @@ -504,12 +504,12 @@ GOVERNANCE lifts ban:

## Cluster 6 Audit Addendum (deregistration & bans)

- **Collateral exit is blocked while a slash is open** (H-05, AUD H-03).
`BondingRegistry` checks `hasOpenSlashProposal(operator)` on every authorized current or retained
historical manager and reverts `OperatorUnderSlash()` from ticket withdrawal, license unbonding,
deregistration, and exit claims. Execution, an upheld appeal, or permissionless appeal expiry
unwinds the counter. After manager rotation, governance must retain the old manager until every
E3 and proposal that depends on it is terminal, then explicitly revoke it.
- **Collateral exit is blocked while a slash is open** (H-05, AUD H-03). `BondingRegistry` checks
`hasOpenSlashProposal(operator)` on every authorized current or retained historical manager and
reverts `OperatorUnderSlash()` from ticket withdrawal, license unbonding, deregistration, and exit
claims. Execution, an upheld appeal, or permissionless appeal expiry unwinds the counter. After
manager rotation, governance must retain the old manager until every E3 and proposal that depends
on it is terminal, then explicitly revoke it.

- **Two-step ban** (M-14, M-15): bans now require `proposeBan` → `confirmBan` from a **distinct**
signer holding `GOVERNANCE_ROLE`. `cancelBan` rescinds an unconfirmed proposal. Legacy direct-set
Expand Down
Loading
Loading