I've been working through the BlockScience reports to figure out how E3 pricing should actually work. They model the fee as a function of committee size, threshold, time availability, decryption scheme, and ciphertext size, broken into key generation, pairwise coordination, availability over time, and decryption costs.
The problem is when I traced through our actual ZK proof pipeline, key generation is not a flat per-node cost like the BlockScience model assumes. Each committee member generates:
proofs_per_node = 6 + 2 × (N-1) × L_dkg
Where $N$ = committee size and $L_{dkg}$ = DKG moduli count. For a 20-node committee, that's 82 proofs per node, 1,640 total proofs across the committee. The cost scales quadratically with committee size, not linearly. On top of that, every node verifies every other node's proofs, so verification is also $O(N^2)$ across the committee.
Issue
For our getE3Quote() if we implement BlockScience's model as-is (flat keyGenPerNode × n), we'd still undercharge by 5-20x because it doesn't capture the proof scaling. We need a fee formula that reflects the actual compute.
There are also several costs the model doesn't account for at all:
- Sortition window: CNs are locked during committee selection but
getE3Quote() doesn't include this duration
- Proof verification: each node verifies all other nodes' proofs, completely unpriced
- Accusation protocol: the 5-min vote timeout in
AccusationManager extends the E3 wall-clock time
- Aggregator work: recursive proof aggregation for C5/C7 circuits + on-chain gas is currently uncompensated
esi_per_ct increases the proof counts significantly for those circuits
Proposed Fee Structure
Split the existing keyGenPerNode into two parameters, a fixed per-node overhead and a per-proof cost that captures the N-scaling.
Given:
-
$N$ = committee size, $M$ = threshold
-
$L$ = DKG moduli count (1 for 512 params, 2 for 8192)
Proof count per node:
$$P = 6 + 2 \times (N - 1) \times L$$
The 6 fixed proofs are C0, C1, C2a, C2b, C4a, C4b. The scaling proofs are C3a/C3b (one per recipient per modulus row).
The cost parameters which are all governance tunable, denominated in fee token:
| Symbol |
Meaning |
fixedPerNode |
per-node setup overhead |
perProof |
cost per ZK proof generated |
perPair |
pairwise coordination cost |
perVerification |
cost per proof verification |
perNodePerSec |
availability cost per node per second |
perDecrypt |
decryption share generation cost per node |
publication |
base on-chain publication cost |
margin |
markup (e.g. 10%) to absorb variance |
Cost components:
$$\text{keygen} = N \times \text{fixedPerNode} + N \times P \times \text{perProof}$$
$$\text{coordination} = \frac{N(N-1)}{2} \times \text{perPair}$$
$$\text{verification} = N \times P \times \text{perVerification}$$
$$\text{availability} = N \times T \times \text{perNodePerSec}$$
$$\text{decryption} = M \times \text{perDecrypt} + \frac{M(M-1)}{2} \times \text{perPair}$$
Where $T$ is the priced duration, using expected-case fractions instead of worst-case timeouts:
$$T = \text{sortitionWindow} + \text{inputWindow} + \alpha_1 \cdot \text{dkgWindow} + \alpha_2 \cdot \text{computeWindow} + \alpha_3 \cdot \text{decryptWindow}$$
Total fee:
$$\text{fee} = (\text{keygen} + \text{coordination} + \text{verification} + \text{availability} + \text{decryption} + \text{publication}) \times (1 + \text{margin})$$
The utilization fractions ($\alpha_1$, $\alpha_2$, $\alpha_3$) are there because the timeout windows are safety limits, not expected durations. If we price availability using the full timeout, we overcharge significantly — a CN that finishes DKG in 15 minutes is free to do other work, but the requester paid for the full 4-hour window.
Example with a 4-hour DKG window: if DKG typically completes in ~1 hour, then $\alpha_1 = 0.25$ means we only charge the requester for 25% of the window (1 hour), which matches the average actual CN lockup time. The timeout exists so the protocol knows when to mark an E3 as failed, it's not how long nodes are actually busy.
The same logic applies to compute ($\alpha_2$) and decryption ($\alpha_3$). Each stage has a worst-case timeout that rarely gets hit. The margin markup is what covers the rare cases where an E3 runs close to the full timeout.
These fractions are governance-tunable, so we can adjust them as we collect data on how long each stage actually takes.
Also for non-selected sortition submitters, nodes submit tickets and pay gas but earn nothing if they're not in the final committee. Do we care about compensating this?
cc @auryn-macmillan @ctrlc03 @ryardley @cedoor @0xjei
I've been working through the BlockScience reports to figure out how E3 pricing should actually work. They model the fee as a function of committee size, threshold, time availability, decryption scheme, and ciphertext size, broken into key generation, pairwise coordination, availability over time, and decryption costs.
The problem is when I traced through our actual ZK proof pipeline, key generation is not a flat per-node cost like the BlockScience model assumes. Each committee member generates:
Where$N$ = committee size and $L_{dkg}$ = DKG moduli count. For a 20-node committee, that's 82 proofs per node, 1,640 total proofs across the committee. The cost scales quadratically with committee size, not linearly. On top of that, every node verifies every other node's proofs, so verification is also $O(N^2)$ across the committee.
Issue
For our
getE3Quote()if we implement BlockScience's model as-is (flatkeyGenPerNode × n), we'd still undercharge by 5-20x because it doesn't capture the proof scaling. We need a fee formula that reflects the actual compute.There are also several costs the model doesn't account for at all:
getE3Quote()doesn't include this durationAccusationManagerextends the E3 wall-clock timeesi_per_ctincreases the proof counts significantly for those circuitsProposed Fee Structure
Split the existing
keyGenPerNodeinto two parameters, a fixed per-node overhead and a per-proof cost that captures the N-scaling.Given:
Proof count per node:
The 6 fixed proofs are C0, C1, C2a, C2b, C4a, C4b. The scaling proofs are C3a/C3b (one per recipient per modulus row).
The cost parameters which are all governance tunable, denominated in fee token:
fixedPerNodeperProofperPairperVerificationperNodePerSecperDecryptpublicationmarginCost components:
Where$T$ is the priced duration, using expected-case fractions instead of worst-case timeouts:
Total fee:
The utilization fractions ($\alpha_1$ , $\alpha_2$ , $\alpha_3$ ) are there because the timeout windows are safety limits, not expected durations. If we price availability using the full timeout, we overcharge significantly — a CN that finishes DKG in 15 minutes is free to do other work, but the requester paid for the full 4-hour window.
Example with a 4-hour DKG window: if DKG typically completes in ~1 hour, then$\alpha_1 = 0.25$ means we only charge the requester for 25% of the window (1 hour), which matches the average actual CN lockup time. The timeout exists so the protocol knows when to mark an E3 as failed, it's not how long nodes are actually busy.
The same logic applies to compute ($\alpha_2$ ) and decryption ($\alpha_3$ ). Each stage has a worst-case timeout that rarely gets hit. The margin markup is what covers the rare cases where an E3 runs close to the full timeout.
These fractions are governance-tunable, so we can adjust them as we collect data on how long each stage actually takes.
Also for non-selected sortition submitters, nodes submit tickets and pay gas but earn nothing if they're not in the final committee. Do we care about compensating this?
cc @auryn-macmillan @ctrlc03 @ryardley @cedoor @0xjei