Skip to content

Commit 3b08c05

Browse files
authored
docs: clear up certificate verification (#1515)
**Motivation:** We want more descriptive documentation for the `CertificateVerifier` **Modifications:** - Update natspec for `CertificateVerifier`, along with meaning of `maxStalenessPeriod` - Update docs for above **Result:** Clearer documentation
1 parent bb7915a commit 3b08c05

File tree

25 files changed

+143
-61
lines changed

25 files changed

+143
-61
lines changed

docs/multichain/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ Transporter --> Generator: Gets Root
7171
Transporter --> OperatorTableUpdater: Confirms Root, Updates Tables
7272
OperatorTableUpdater --> CertificateVerifier: Updates table
7373
```
74+
75+
The protocol proceeds in the following process:
76+
77+
1. AVS deploys `AVSRegistrar` , configures metadata in EL, and gets operator registration
78+
1. AVS registers for generation/transport calling `CrossChainRegistry.makeGenerationReservation`
79+
2. The AVS deploys an `OperatorTableCalculator`
80+
2. At some cadence, the `Generator`` process gets all active generations from the `CrossChainRegistry` against the latest `finalizedBlock`
81+
1. It then creates and signs a `globalTableRoot` of all operator table commitments
82+
3. The transporter will generate a Certificate to validate that the Eigen Labs Operator signed off on the `globalTableRoot`. The root is then transported to ALL destination chains
83+
4. Lastly, the transporter will update all Operator Tables with a certificate. The sidecar will generate the proof data to then update tables via the `OperatorTableUpdater`
84+
7485
---
7586

7687
### Source Chain

docs/multichain/destination/CertificateVerifier.md

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The CertificateVerifier contracts are responsible for verifying certificates fro
2626

2727
Both verifiers implement staleness checks based on a `maxStalenessPeriod` to ensure certificates are not verified against outdated operator information.
2828

29-
*Note: Setting a max staleness period to 0 enables certificates to be confirmed against any `referenceTimestamp`*.
29+
**Note: Setting a max staleness period to 0 enables certificates to be confirmed against any `referenceTimestamp`. In addition, setting a `maxStalenessPeriod` that is greater than 0 and less than the frequency of table updates (daily on testnet, weekly on mainnet) can result in certificates be unable to be confirmed.** See the [staleness period](#staleness-period) in the appendix for some examples.
3030

3131
---
3232

@@ -60,7 +60,7 @@ struct ECDSAOperatorInfo {
6060
* @param referenceTimestamp the timestamp at which the operatorInfos were sourced
6161
* @param operatorInfos the operatorInfos to update the operator table with
6262
* @param operatorSetConfig the configuration of the operatorSet
63-
* @dev only callable by the operatorTableUpdater for the given operatorSet
63+
* @dev Only callable by the `OperatorTableUpdater`
6464
* @dev The `referenceTimestamp` must be greater than the latest reference timestamp for the given operatorSet
6565
*/
6666
function updateOperatorTable(
@@ -73,6 +73,8 @@ function updateOperatorTable(
7373

7474
Updates the operator table with new `operatorInfos` and `operatorSetConfig`. All operators and weights are written to storage.
7575

76+
Note that updating operator tables for a `referenceTimestamp` that is less than the latest reference timestamp is not possible. Thus, operator tables cannot be updated retroactively. AVS developers should keep this in mind when building their off-chain signature aggregation logic.
77+
7678
*Effects*:
7779
* Stores the number of operators at `_numOperators[operatorSetKey][referenceTimestamp]`
7880
* Stores each operator info at `_operatorInfos[operatorSetKey][referenceTimestamp][index]`
@@ -97,7 +99,8 @@ The contract supports 3 verification patterns:
9799
```solidity
98100
/**
99101
* @notice A ECDSA Certificate
100-
* @param referenceTimestamp the timestamp at which the certificate was created
102+
* @param referenceTimestamp the timestamp at which the certificate was created,
103+
* which corresponds to a reference timestamp of the operator table update
101104
* @param messageHash the hash of the message that was signed by operators
102105
* @param sig the concatenated signature of each signing operator
103106
*/
@@ -282,8 +285,9 @@ struct BN254OperatorSetInfo {
282285
* @param referenceTimestamp the timestamp at which the operatorInfos were sourced
283286
* @param operatorSetInfo the operatorInfos to update the operator table with
284287
* @param operatorSetConfig the configuration of the operatorSet
285-
* @dev only callable by the operatorTableUpdater for the given operatorSet
286-
* @dev The `referenceTimestamp` must be greater than the latest reference timestamp for the given operatorSet
288+
* @dev Only callable by the `OperatorTableUpdater`
289+
* @dev The `referenceTimestamp` must correspond to a reference timestamp for a globalTableRoot stored in the `OperatorTableUpdater`.
290+
* It must also be greater than the latest reference timestamp for the given operatorSet.
287291
*/
288292
function updateOperatorTable(
289293
OperatorSet calldata operatorSet,
@@ -295,6 +299,8 @@ function updateOperatorTable(
295299

296300
Updates the operator table with new `operatorSetInfo` and `operatorSetConfig`.
297301

302+
Note that updating operator tables for a `referenceTimestamp` that is less than the latest reference timestamp is not possible. Thus, operator tables cannot be updated retroactively. AVS developers should keep this in mind when building their off-chain signature aggregation logic.
303+
298304
*Effects*:
299305
* Stores `operatorSetInfo` at `_operatorSetInfos[operatorSetKey][referenceTimestamp]` containing:
300306
* `operatorInfoTreeRoot` - Merkle root of all operator information, each leaf is a `BN254OperatorInfo`
@@ -321,7 +327,8 @@ The contract supports 3 verification patterns:
321327
```solidity
322328
/**
323329
* @notice A BN254 Certificate
324-
* @param referenceTimestamp the timestamp at which the certificate was created
330+
* @param referenceTimestamp the timestamp at which the certificate was created,
331+
* which corresponds to the reference timestamp of the operator table update
325332
* @param messageHash the hash of the message that was signed by operators and used to verify the aggregated signature
326333
* @param signature the G1 signature of the message
327334
* @param apk the G2 aggregate public key
@@ -339,8 +346,8 @@ struct BN254Certificate {
339346
* @notice verifies a certificate
340347
* @param operatorSet the operatorSet that the certificate is for
341348
* @param cert a certificate
342-
* @return signedStakes amount of stake that signed the certificate for each stake
343-
* type. Each index corresponds to a stake type in the `totalWeights` array in the `BN254OperatorSetInfo`.
349+
* @return signedStakes amount of stake that signed the certificate for each stake type. Each index
350+
* corresponds to a stake type in the `totalWeights` array in the `BN254OperatorSetInfo`.
344351
*/
345352
function verifyCertificate(
346353
OperatorSet memory operatorSet,
@@ -376,9 +383,9 @@ Verifies a BN254 certificate by checking the aggregated signature against the op
376383
* @param operatorSet the operatorSet that the certificate is for
377384
* @param cert a certificate
378385
* @param totalStakeNominalThresholds the nominal amount of stake that
379-
* the signed stake of the certificate should meet. Each index corresponds to
380-
* a stake type in the `totalWeights` array in the `BN254OperatorSetInfo`.
381-
* @return whether or not certificate is valid and meets thresholds
386+
* the signed stake of the certificate should meet. Each index corresponds to
387+
* a stake type in the `totalWeights` array in the `BN254OperatorSetInfo`.
388+
* @return whether or not certificate is valid and meets nominal thresholds
382389
*/
383390
function verifyCertificateNominal(
384391
OperatorSet memory operatorSet,
@@ -408,11 +415,11 @@ Verifies that a certificate meets specified nominal (absolute) stake thresholds
408415
* @notice verifies a certificate and makes sure that the signed stakes meet
409416
* provided portions of the total stake on the AVS
410417
* @param operatorSet the operatorSet that the certificate is for
411-
* @param cert a certificate
418+
* @param cert the certificate
412419
* @param totalStakeProportionThresholds the proportion, in BPS,of total stake that
413-
* the signed stake of the certificate should meet. Each index corresponds to
414-
* a stake type in the `totalWeights` array in the `BN254OperatorSetInfo`.
415-
* @return whether or not certificate is valid and meets thresholds
420+
* the signed stake of the certificate should meet. Each index corresponds to
421+
* a stake type in the `totalWeights` array in the `BN254OperatorSetInfo`.
422+
* @return whether or not certificate is valid and meets proportion thresholds
416423
*/
417424
function verifyCertificateProportion(
418425
OperatorSet memory operatorSet,
@@ -440,10 +447,12 @@ Verifies that a certificate meets specified proportion thresholds as a percentag
440447

441448
```solidity
442449
/**
443-
* @notice A witness for an operator
450+
* @notice A witness for an operator, used to identify the non-signers for a given certificate
444451
* @param operatorIndex the index of the nonsigner in the `BN254OperatorInfo` tree
445-
* @param operatorInfoProof merkle proofs of the nonsigner at the index. Empty if operator is in cache.
446-
* @param operatorInfo the `BN254OperatorInfo` for the operator. Empty if operator is in cache
452+
* @param operatorInfoProofs merkle proof of the nonsigner at the index. Empty if the non-signing operator is already stored from a previous verification
453+
* @param operatorInfo the `BN254OperatorInfo` for the operator. Empty if the non-signing operator is already stored from a previous verification
454+
* @dev Non-signing operators are stored in the `BN254CertificateVerifier` upon the first successful certificate verification. This is done to avoid
455+
* the need for resupplying proofs of non-signing operators for each certificate verification.
447456
*/
448457
struct BN254OperatorInfoWitness {
449458
uint32 operatorIndex;
@@ -464,3 +473,29 @@ flowchart TB
464473
N1 --> L2[[Leaf 2<br/>BN254OperatorInfo #2]]
465474
N1 --> L3[[Leaf 3<br/>BN254OperatorInfo #3]]
466475
```
476+
477+
---
478+
479+
## Appendix
480+
481+
### Staleness Period
482+
483+
For the below examples, let's assume that the operator table is updated on Day 1
484+
485+
#### Eg. 1: Normal Functioning
486+
Assume the the staleness period is 10 days and the `referenceTimestamp` of a certificate is Day 1.
487+
488+
1. Day 1: Table Updated
489+
2. Day 9: Certificate passes
490+
3. Day 10: Certificate passes
491+
4. Day 11: Certificate verification *fails*
492+
493+
#### Eg. 2: Low staleness period
494+
The operator table is updated every 10 days. The staleness period is 5 days. The `referenceTimestamp` of a certificate is Day 1.
495+
496+
1. Day 1: Table updated
497+
2. Day 2: Certificate passes
498+
3. Day 6: Certifiacte verification *fails*
499+
4. Day 7: A certificate is re-generated. However, this will stale fail as the `referenceTimestamp` would still be day 1 given that was the latest table update
500+
501+
Note that we cannot re-generate a certificate on Day 7. This is why we recommend that the `stalenessPeriod` is greater than or equal to the update cadence of operator tables.

docs/multichain/destination/OperatorTableUpdater.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ The following values are set upon initialization:
3131
* `maxStalenessPeriod`: 0. Set to zero to confirm `globalTableRoots` without updating the `generator` operatorSet. See [`CertificateVerifier`](./CertificateVerifier.md#overview) for specifics`OperatorTableUpdater`. It is the same across all destination chains, even for destination chains that are supported after the initial deployment.
3232
* `owner`: Unused parameter for `Generator`
3333

34-
34+
Operator tables are updated daily on testnet and weekly on mainnet.
3535
---
3636

3737
## Global Root Confirmation

docs/multichain/source/CrossChainRegistry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ The `CrossChainRegistry` manages the registration/deregistration of operatorSets
2121
* @notice A per-operatorSet configuration struct that is transported from the CrossChainRegistry on L1.
2222
* @param owner the permissioned owner of the OperatorSet on L2 that can call the CertificateVerifier specific setters
2323
* @param maxStalenessPeriod the maximum staleness period of the operatorSet
24+
*
25+
* @dev A staleness period of 0 allows for certificates to be verified against any timestamp in the past
26+
* @dev Staleness periods should not be greater than 0 and less than the update cadence of the `OperatorTables`, since
27+
* certificates would be unable to be validated against. The update cadence is communicated off-chain
2428
*/
2529
struct OperatorSetConfig {
2630
address owner;
@@ -150,6 +154,7 @@ Updates the `operatorTableCalculator` contract for a given `operatorSet`. The `o
150154
* @param config the config to set
151155
* @dev msg.sender must be UAM permissioned for operatorSet.avs
152156
* @dev operatorSet must have an active generation reservation
157+
* @dev The max staleness period is NOT checkpointed and is applied globally regardless of the reference timestamp of a certificate
153158
*/
154159
function setOperatorSetConfig(
155160
OperatorSet calldata operatorSet,

pkg/bindings/BN254CertificateVerifier/binding.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/bindings/CrossChainRegistry/binding.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/bindings/DelegationManager/binding.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)