|
| 1 | +## OperatorTableUpdater |
| 2 | + |
| 3 | +| File | Type | Proxy | |
| 4 | +| -------- | -------- | -------- | |
| 5 | +| [`OperatorTableUpdater.sol`](../../../src/contracts/multichain/OperatorTableUpdater.sol) | Singleton | Transparent Proxy | |
| 6 | + |
| 7 | +Libraries and Mixins: |
| 8 | + |
| 9 | +| File | Notes | |
| 10 | +| -------- | -------- | |
| 11 | +| [`OwnableUpgradeable.sol`](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/v4.9.0/contracts/access/OwnableUpgradeable.sol) | Access control | |
| 12 | +| [`SemVerMixin.sol`](../../../src/contracts/mixins/SemVerMixin.sol) | Versioning | |
| 13 | +| [`Merkle.sol`](../../../src/contracts/libraries/Merkle.sol) | Merkle proof verification | |
| 14 | + |
| 15 | +## Overview |
| 16 | + |
| 17 | +The `OperatorTableUpdater` is responsible for updating the `GlobalTableRoot` and updating operator tables from merkle proofs against the `GlobalTableRoot`. The contract is deployed on every destination chain. The contract maintains a set of valid global table roots that are confirmed by a designated global root confirmer set, and allows updating individual operator tables by providing merkle proofs against these roots. |
| 18 | + |
| 19 | +The contract supports both BN254 and ECDSA operator tables and routes updates to the appropriate certificate verifier based on the curve type. |
| 20 | + |
| 21 | +## Parameterization |
| 22 | +Upon initialization, the `globalRootConfirmerSet` (ie. `Generator`) is updated. This operatorSet is a *"shadow-operatorSet"*. It does not exist in the core protocol, does not have stake backing it, and is not transported to other chains via the multichain protocol. It can only be updated upon initialization or by a [privileged role](#updateglobalrootconfirmerset). This entity is the same across all destination chains. |
| 23 | + |
| 24 | +* `GlobalRootConfirmerSet`, also known as the `Generator`, is an EigenLabs-run entity that signs off on `GlobalTableRoots`. The operatorSet is of size 1. |
| 25 | +* `maxStalenessPeriod`: 0. Set to zero to confirm roots without updating the `globalConfirmerOperatorSet`. See [`CertificateVerifier`](./CertificateVerifier.md#overview) for specifics |
| 26 | +* `globalRootConfirmationThreshold`: 10000. The threshold in basis points required for global root confirmation. Since the operatorSet is of size 1 a single signature is needed |
| 27 | +* `referenceTimestamp`: A past timestamp at which the `globalRootConfirmerSet` is generated. This value is set to the initial `latestReferenceTimestamp` in the `OperatorTableUpdater. It is the same across all destination chains, even for destination chains that are supported after the initial deployment |
| 28 | + |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## Global Root Confirmation |
| 33 | + |
| 34 | +Global table roots must be confirmed by the `globalRootConfirmerSet` (ie. `Generator`) before operator tables can be updated against them. |
| 35 | + |
| 36 | +### `confirmGlobalTableRoot` |
| 37 | + |
| 38 | +```solidity |
| 39 | +/** |
| 40 | + * @notice Confirms Global operator table root |
| 41 | + * @param globalTableRootCert certificate of the root |
| 42 | + * @param globalTableRoot merkle root of all operatorSet tables |
| 43 | + * @param referenceTimestamp timestamp of the root |
| 44 | + * @param referenceBlockNumber block number of the root |
| 45 | + * @dev Any entity can submit with a valid certificate signed off by the `globalRootConfirmerSet` |
| 46 | + * @dev The `msgHash` in the `globalOperatorTableRootCert` is the hash of the `globalOperatorTableRoot` |
| 47 | + */ |
| 48 | +function confirmGlobalTableRoot( |
| 49 | + BN254Certificate calldata globalTableRootCert, |
| 50 | + bytes32 globalTableRoot, |
| 51 | + uint32 referenceTimestamp, |
| 52 | + uint32 referenceBlockNumber |
| 53 | +) external; |
| 54 | +``` |
| 55 | + |
| 56 | +Confirms a new global table root by verifying a BN254 certificate signed by the `globalRootConfirmerSet`. See [`BN254CertificateVerifier`](./CertificateVerifier.md#bn254certificateverifier) for certificate verification. Roots are append only and cannot be overridden, only [disabled](#disableroot). |
| 57 | + |
| 58 | +*Effects*: |
| 59 | +* Updates `_latestReferenceTimestamp` to the new `referenceTimestamp` |
| 60 | +* Sets `_referenceBlockNumbers[referenceTimestamp]` to `referenceBlockNumber` |
| 61 | +* Sets `_referenceTimestamps[referenceBlockNumber]` to `referenceTimestamp` |
| 62 | +* Sets `_globalTableRoots[referenceTimestamp]` to `globalTableRoot` |
| 63 | +* Sets `_isRootValid[globalTableRoot]` to `true` |
| 64 | +* Emits a `NewGlobalTableRoot` event |
| 65 | + |
| 66 | +*Requirements*: |
| 67 | +* The `referenceTimestamp` MUST NOT be in the future |
| 68 | +* The `referenceTimestamp` MUST be greater than `_latestReferenceTimestamp` |
| 69 | +* The certificate's `messageHash` MUST match the expected EIP-712 hash |
| 70 | +* The certificate MUST be valid according to the `globalRootConfirmationThreshold` |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +## Operator Table Updates |
| 75 | + |
| 76 | +Once a global root is confirmed, individual operator tables can be updated by providing merkle proofs against the root. |
| 77 | + |
| 78 | +### `updateOperatorTable` |
| 79 | + |
| 80 | +```solidity |
| 81 | +/** |
| 82 | + * @notice Updates an operator table |
| 83 | + * @param referenceTimestamp the reference block number of the globalTableRoot |
| 84 | + * @param globalTableRoot the new globalTableRoot |
| 85 | + * @param operatorSetIndex the index of the given operatorSet being updated |
| 86 | + * @param proof the proof of the leaf at index against the globalTableRoot |
| 87 | + * @param operatorTableBytes the bytes of the operator table |
| 88 | + * @dev Depending on the decoded KeyType, the tableInfo will be decoded |
| 89 | + */ |
| 90 | +function updateOperatorTable( |
| 91 | + uint32 referenceTimestamp, |
| 92 | + bytes32 globalTableRoot, |
| 93 | + uint32 operatorSetIndex, |
| 94 | + bytes calldata proof, |
| 95 | + bytes calldata operatorTableBytes |
| 96 | +) external; |
| 97 | +``` |
| 98 | + |
| 99 | +Updates an operator table by verifying its inclusion in a confirmed global table root via merkle proof. The function decodes the operator table data and routes the update to the appropriate certificate verifier based on the curve type. |
| 100 | + |
| 101 | +*Effects*: |
| 102 | +* For BN254 operator sets: |
| 103 | + * Calls `bn254CertificateVerifier.updateOperatorTable` with the decoded operator info |
| 104 | +* For ECDSA operator sets: |
| 105 | + * Calls `ecdsaCertificateVerifier.updateOperatorTable` with the decoded operator info |
| 106 | + |
| 107 | +*Requirements*: |
| 108 | +* The `globalTableRoot` MUST be valid (not disabled) |
| 109 | +* The `referenceTimestamp` MUST be greater than the latest timestamp for the operator set |
| 110 | +* The merkle proof MUST verify the operator table's inclusion in the global root |
| 111 | +* The `globalTableRoot` at `referenceTimestamp` MUST match the provided root |
| 112 | +* Meets all requirements in [`ecdsaCertificateVerifier.updateOperatorTable`](./CertificateVerifier.md#updateoperatortable) or [`bn254CertificateVerifier.updateOperatorTable`](./CertificateVerifier.md#updateoperatortable-1) |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +## System Configuration |
| 117 | + |
| 118 | +The `owner` can configure the `globalRootConfirmerSet` and confirmation parameters. |
| 119 | + |
| 120 | +### `setGlobalRootConfirmerSet` |
| 121 | + |
| 122 | +```solidity |
| 123 | +/** |
| 124 | + * @notice Set the operatorSet which certifies against global roots |
| 125 | + * @param operatorSet the operatorSet which certifies against global roots |
| 126 | + * @dev The `operatorSet` is used to verify the certificate of the global table root |
| 127 | + * @dev Only callable by the owner of the contract |
| 128 | + */ |
| 129 | +function setGlobalRootConfirmerSet( |
| 130 | + OperatorSet calldata operatorSet |
| 131 | +) external; |
| 132 | +``` |
| 133 | + |
| 134 | +Updates the operator set responsible for confirming global table roots. |
| 135 | + |
| 136 | +*Effects*: |
| 137 | +* Updates `_globalRootConfirmerSet` to the new `operatorSet` |
| 138 | +* Emits a `GlobalRootConfirmerSetUpdated` event |
| 139 | + |
| 140 | +*Requirements*: |
| 141 | +* Caller MUST be the `owner` |
| 142 | + |
| 143 | +### `setGlobalRootConfirmationThreshold` |
| 144 | + |
| 145 | +```solidity |
| 146 | +/** |
| 147 | + * @notice The threshold, in bps, for a global root to be signed off on and updated |
| 148 | + * @param bps The threshold in basis points |
| 149 | + * @dev Only callable by the owner of the contract |
| 150 | + */ |
| 151 | +function setGlobalRootConfirmationThreshold( |
| 152 | + uint16 bps |
| 153 | +) external; |
| 154 | +``` |
| 155 | + |
| 156 | +Sets the stake proportion threshold required for confirming global table roots. |
| 157 | + |
| 158 | +*Effects*: |
| 159 | +* Updates `globalRootConfirmationThreshold` to `bps` |
| 160 | +* Emits a `GlobalRootConfirmationThresholdUpdated` event |
| 161 | + |
| 162 | +*Requirements*: |
| 163 | +* Caller MUST be the `owner` |
| 164 | +* `bps` MUST NOT exceed `MAX_BPS` (10000) |
| 165 | + |
| 166 | +### `disableRoot` |
| 167 | + |
| 168 | +```solidity |
| 169 | +/** |
| 170 | + * @notice Disables a global table root |
| 171 | + * @param globalTableRoot the global table root to disable |
| 172 | + * @dev Only callable by the owner of the contract |
| 173 | + */ |
| 174 | +function disableRoot( |
| 175 | + bytes32 globalTableRoot |
| 176 | +) external; |
| 177 | +``` |
| 178 | + |
| 179 | +Disables a global table root, preventing further operator table updates against it. This function also prevents the `CertificateVerifier` from verifying certificates. The function is intended to prevent a malicious or invalid root from being used by downstream consumers. |
| 180 | + |
| 181 | +*Effects*: |
| 182 | +* Sets `_isRootValid[globalTableRoot]` to `false` |
| 183 | +* Emits a `GlobalRootDisabled` event |
| 184 | + |
| 185 | +*Requirements*: |
| 186 | +* Caller MUST be the `owner` |
| 187 | +* The `globalTableRoot` MUST exist and be currently valid |
| 188 | + |
| 189 | +### `updateGlobalRootConfirmerSet` |
| 190 | + |
| 191 | +```solidity |
| 192 | +/** |
| 193 | + * @notice Updates the operator table for the global root confirmer set |
| 194 | + * @param referenceTimestamp The reference timestamp of the operator table update |
| 195 | + * @param globalRootConfirmerSetInfo The operatorSetInfo for the global root confirmer set |
| 196 | + * @param globalRootConfirmerSetConfig The operatorSetConfig for the global root confirmer set |
| 197 | + * @dev We have a separate function for updating this operatorSet since it's not transported and updated |
| 198 | + * in the same way as the other operatorSets |
| 199 | + * @dev Only callable by the owner of the contract |
| 200 | + */ |
| 201 | +function updateGlobalRootConfirmerSet( |
| 202 | + uint32 referenceTimestamp, |
| 203 | + BN254OperatorSetInfo calldata globalRootConfirmerSetInfo, |
| 204 | + OperatorSetConfig calldata globalRootConfirmerSetConfig |
| 205 | +) external; |
| 206 | +``` |
| 207 | + |
| 208 | +Updates the operator table for the `globalRootConfirmerSet` itself. This operatorSet is a ["shadow-operatorSet"](#parameterization), so it must be updated manually |
| 209 | + |
| 210 | +*Effects*: |
| 211 | +* Calls `bn254CertificateVerifier.updateOperatorTable` for the `globalRootConfirmerSet` |
| 212 | + |
| 213 | +*Requirements*: |
| 214 | +* Caller MUST be the `owner` |
| 215 | +* Meet all requirements in [`bn254CertificateVerifier.updateOperatorTable`](../destination/CertificateVerifier.md#updateoperatortable-1) |
0 commit comments