Skip to content

Commit f0e4d18

Browse files
committed
feat: multichain interfaces (#477)
**Motivation:** Initial interfaces for multi chain. **Modifications:** ***TableCalculator*** The separation here is designed to decouple - Curve-Specific Calculation - Generic Table Calculation Getters (applicable for all curve types) - Weighting. `IOperatorWeightCalculator` is a calculation contract that defines how to weigh stakes of an operatorSet. This contract may or may not be stateless. In practice, this can be an external contract or library. ```mermaid classDiagram IOperatorWeightCalculator <-- IOperatorTableCalculator : uses many IOperatorTableCalculator <|-- IECDSATableCalculator : implements IOperatorTableCalculator <|-- IBN254TableCalculator : implements class IOperatorWeightCalculator { +getOperatorWeights(OperatorSet) } class IOperatorTableCalculator { +setOperatorWeightCalculator(OperatorSet, IOperatorWeightCalculator) +calculateOperatorTableBytes(OperatorSet) returns (bytes) +getOperatorWeightCalculator(OperatorSet) returns (IOperatorWeightCalculator) } class IECDSATableCalculator { +calculateOperatorTable(OperatorSet) returns (ECDSAOperatorInfo[]) } class IBN254TableCalculator { +calculateOperatorTable(OperatorSet) returns (BN254OperatorSetInfo) +getOperatorInfos(OperatorSet) returns (BN254OperatorInfo[]) } ``` ***CertificateVerifier*** The `CertificateVerifier` decouples setting of the table and verification. See below: ```mermaid classDiagram ICertificateVerifier <|-- IBN254CertificateVerifier: implements IBN254TableManager <|-- IBN254CertificateVerifier: implements class ICertificateVerifier { <<interface>> +setOperatorTableUpdater(address) +setEjector(address) +setMaxOperatorTableStaleness(uint32) +operatorSet() returns (OperatorSet) +operatorTableUpdater() returns (address) +ejector() returns (address) +maxOperatorTableStaleness() returns (uint32) +latestReferenceTimestamp() returns (uint32) } class IBN254TableManager { <<interface>> +updateOperatorTable(OperatorSet, uint32, BN254OperatorSetInfo) +ejectOperators(OperatorSet, uint32, uint32[], BN254OperatorInfoWitness[]) } class IBN254CertificateVerifier { <<interface>> +verifyCertificate(BN254Certificate) returns (uint96[]) +verifyCertificateProportion(BN254Certificate, uint16[]) returns (bool) +verifyCertificateNominal(BN254Certificate, uint96[]) returns (bool) } ``` ***Migration Story*** We want a migration path to store all tables in a singleton core contract. In order to do so, we future-proofed the _transportation_ interface to pass in an `operatorSet` when updating an operatorTable. Permissions setting can be done by an EOA, so we don't need to make that forwards compatible. If all the tables live in a single contract, then for Bn254 caching, the verification must cache stakes in the singleton. **Result:** Initial Interfaces. I see these changing for the following reasons: - Encoding leafs with a salt - Table generation-based trusted operator table updates - Multiquorum sig support (but EigenDA can build their own)
1 parent 3fb5b61 commit f0e4d18

7 files changed

+434
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {BN254} from "../../libraries/BN254.sol";
5+
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
6+
import {IBN254TableCalculatorTypes} from "./IBN254TableCalculator.sol";
7+
import {ICertificateVerifier} from "./ICertificateVerifier.sol";
8+
9+
interface IBN254CertificateVerifierTypes is IBN254TableCalculatorTypes {
10+
/**
11+
* @notice A witness for an operator
12+
* @param operatorIndex the index of the nonsigner in the `BN254OperatorInfo` tree
13+
* @param operatorInfoProofs merkle proofs of the nonsigner at the index. Empty if operator is in cache.
14+
* @param operatorInfo the `BN254OperatorInfo` for the operator
15+
*/
16+
struct BN254OperatorInfoWitness {
17+
uint32 operatorIndex;
18+
bytes operatorInfoProof;
19+
BN254OperatorInfo operatorInfo;
20+
}
21+
22+
/**
23+
* @notice A BN254 Certificate
24+
* @param referenceTimestamp the timestamp at which the certificate was created
25+
* @param messageHash the hash of the message that was signed by operators and used to verify the aggregated signature
26+
* @param signature the G1 signature of the message
27+
* @param apk the G2 aggregate public key
28+
* @param nonSignerWitnesses an array of witnesses of non-signing operators
29+
*/
30+
struct BN254Certificate {
31+
uint32 referenceTimestamp;
32+
bytes32 messageHash;
33+
BN254.G1Point signature;
34+
BN254.G2Point apk;
35+
BN254OperatorInfoWitness[] nonSignerWitnesses;
36+
}
37+
}
38+
39+
interface IBN254CertificateVerifierEvents is IBN254CertificateVerifierTypes {
40+
/// @notice Emitted when a table is updated
41+
event TableUpdated(uint32 referenceTimestamp, BN254OperatorSetInfo operatorSetInfo);
42+
}
43+
44+
/// @notice A base table manager interface that handles operator table updates
45+
/// @dev We separate out this interface for forwards-compatibility with a future `TableManager` contract that stores all operatorSet's tables on a chain
46+
interface IBN254TableManager is IBN254CertificateVerifierTypes {
47+
/**
48+
* @notice updates the operator table
49+
* @param operatorSet the operatorSet to update the operator table for
50+
* @param referenceTimestamp the timestamp at which the operatorSetInfo and
51+
* operatorInfoTreeRoot were sourced
52+
* @param operatorSetInfo the aggregate information about the operatorSet
53+
* @dev only callable by the operatorTableUpdater
54+
* @dev We pass in an `operatorSet` for future-proofing a global `TableManager` contract
55+
*/
56+
function updateOperatorTable(
57+
OperatorSet calldata operatorSet,
58+
uint32 referenceTimestamp,
59+
BN254OperatorSetInfo memory operatorSetInfo
60+
) external;
61+
62+
/**
63+
* @notice ejects operators from the operatorSet
64+
* @param referenceTimestamp the timestamp of the operator tbale against which
65+
* the ejection is being done
66+
* @param operatorIndices the indices of the operators to eject
67+
* @param witnesses for the operators that are not already in storage
68+
* @dev only callable by the ejector
69+
* @dev We pass in an `operatorSet` for future-proofing a global `TableManager` contract
70+
*/
71+
function ejectOperators(
72+
OperatorSet calldata operatorSet,
73+
uint32 referenceTimestamp,
74+
uint32[] calldata operatorIndices,
75+
BN254OperatorInfoWitness[] calldata witnesses
76+
) external;
77+
}
78+
79+
interface IBN254CertificateVerifier is
80+
ICertificateVerifier,
81+
IBN254TableManager,
82+
IBN254CertificateVerifierEvents
83+
{
84+
/**
85+
* @notice verifies a certificate
86+
* @param cert a certificate
87+
* @return signedStakes amount of stake that signed the certificate for each stake
88+
* type
89+
*/
90+
function verifyCertificate(
91+
BN254Certificate memory cert
92+
) external returns (uint96[] memory signedStakes);
93+
94+
/**
95+
* @notice verifies a certificate and makes sure that the signed stakes meet
96+
* provided portions of the total stake on the AVS
97+
* @param cert a certificate
98+
* @param totalStakeProportionThresholds the proportion of total stake that
99+
* the signed stake of the certificate should meet
100+
* @return whether or not certificate is valid and meets thresholds
101+
*/
102+
function verifyCertificateProportion(
103+
BN254Certificate memory cert,
104+
uint16[] memory totalStakeProportionThresholds
105+
) external returns (bool);
106+
107+
/**
108+
* @notice verifies a certificate and makes sure that the signed stakes meet
109+
* provided nominal stake thresholds
110+
* @param cert a certificate
111+
* @param totalStakeNominalThresholds the nominal amount of stake that
112+
* the signed stake of the certificate should meet
113+
* @return whether or not certificate is valid and meets thresholds
114+
*/
115+
function verifyCertificateNominal(
116+
BN254Certificate memory cert,
117+
uint96[] memory totalStakeNominalThresholds
118+
) external returns (bool);
119+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {BN254} from "../../libraries/BN254.sol";
5+
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
6+
import {IOperatorTableCalculator} from "./IOperatorTableCalculator.sol";
7+
8+
interface IBN254TableCalculatorTypes {
9+
/**
10+
* @notice A struct that contains information about a single operator
11+
* @param pubkey The G1 public key of the operator.
12+
* @param weights The weights of the operator for a single operatorSet.
13+
* @dev The `weights` array can be defined as a list of arbitrary groupings. For example,
14+
* it can be [slashable_stake, delegated_stake, strategy_i_stake, ...]
15+
*/
16+
struct BN254OperatorInfo {
17+
BN254.G1Point pubkey;
18+
uint96[] weights;
19+
}
20+
21+
/**
22+
* @notice A struct that contains information about all operators for a given operatorSet
23+
* @param operatorInfoTreeRoot The root of the operatorInfo tree.
24+
* @param numOperators The number of operators in the operatorSet.
25+
* @param aggregatePubkey The aggregate G1 public key of the operators in the operatorSet.
26+
* @param totalWeights The total weights of the operators in the operatorSet.
27+
*
28+
* @dev The operatorInfoTreeRoot is the root of a merkle tree that contains the operatorInfos for each operator in the operatorSet.
29+
* It is calculated in this function and used by the `IBN254CertificateVerifier` to verify stakes against the non-signing operators
30+
*
31+
* @dev Retrieval of the `aggregatePubKey` depends on maintaining a key registry contract, see `BLSAPKRegistry` for an example implementation.
32+
*
33+
* @dev The `totalWeights` array should be the same length as each individual `weights` array in `operatorInfos`.
34+
*/
35+
struct BN254OperatorSetInfo {
36+
bytes32 operatorInfoTreeRoot;
37+
uint256 numOperators;
38+
BN254.G1Point aggregatePubkey;
39+
uint96[] totalWeights;
40+
}
41+
}
42+
43+
interface IBN254TableCalculator is IOperatorTableCalculator, IBN254TableCalculatorTypes {
44+
/**
45+
* @notice calculates the operatorInfos for a given operatorSet
46+
* @param operatorSet the operatorSet to calculate the operator table for
47+
* @return operatorSetInfo the operatorSetInfo for the given operatorSet
48+
* @dev The output of this function is converted to bytes via the `calculateOperatorTableBytes` function
49+
*/
50+
function calculateOperatorTable(
51+
OperatorSet calldata operatorSet
52+
) external view returns (BN254OperatorSetInfo memory operatorSetInfo);
53+
54+
/**
55+
* @notice Get the operatorInfos for a given operatorSet
56+
* @param operatorSet the operatorSet to get the operatorInfos for
57+
* @return operatorInfos the operatorInfos for the given operatorSet
58+
*/
59+
function getOperatorInfos(
60+
OperatorSet calldata operatorSet
61+
) external view returns (BN254OperatorInfo[] memory operatorInfos);
62+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
5+
6+
interface ICertificateVerifierErrors {
7+
/// @notice Thrown when the table updater is not caller
8+
error OnlyTableUpdater();
9+
/// @notice Thrown when the table is too stale
10+
error TableStale();
11+
/// @notice Thrown when certificate verification fails
12+
error CertVerificationFailed();
13+
}
14+
15+
/// @notice A base interface that verifies certificates for a given operatorSet
16+
/// @notice This is a base interface that all curve certificate verifiers (eg. BN254, ECDSA) must implement
17+
/// @dev A single `CertificateVerifier` can be used for ONLY 1 operatorSet
18+
interface ICertificateVerifier is ICertificateVerifierErrors {
19+
/**
20+
* @notice sets the operator table updater
21+
* @param operatorTableUpdater the address of the operator table updater
22+
* @dev only callable by the owner
23+
*/
24+
function setOperatorTableUpdater(
25+
address operatorTableUpdater
26+
) external;
27+
28+
/**
29+
* @notice Sets the ejector
30+
* @param ejector the address of the ejector
31+
* @dev only callable by the owner
32+
*/
33+
function setEjector(
34+
address ejector
35+
) external;
36+
37+
/**
38+
* @notice sets the max operator table staleness
39+
* @param maxOperatorTableStaleness the max operator table staleness
40+
* @dev only callable by the owner
41+
*/
42+
function setMaxOperatorTableStaleness(
43+
uint32 maxOperatorTableStaleness
44+
) external;
45+
46+
/// @notice the operatorSet the CertificateVerifier is for
47+
function operatorSet() external returns (OperatorSet memory);
48+
49+
/// @notice the address of the entity that can update the operator table
50+
function operatorTableUpdater() external returns (address);
51+
52+
/// @notice the address of the entity that can eject operators
53+
function ejector() external returns (address);
54+
55+
/// @return the maximum amount of seconds that a operator table can be in the past
56+
function maxOperatorTableStaleness() external returns (uint32);
57+
58+
/// @notice The latest reference timestamp of the operator table
59+
function latestReferenceTimestamp() external returns (uint32);
60+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
5+
import {ICertificateVerifier} from "./ICertificateVerifier.sol";
6+
import {IECDSATableCalculatorTypes} from "./IECDSATableCalculator.sol";
7+
8+
interface IECDSCertificateVerifierTypes is IECDSATableCalculatorTypes {
9+
/**
10+
* @notice A ECDSA Certificate
11+
* @param referenceTimestamp the timestamp at which the certificate was created
12+
* @param messageHash the hash of the message that was signed by operators
13+
* @param signature the concatenated signature of each signing operator
14+
*/
15+
struct ECDSACertificate {
16+
uint32 referenceTimestamp;
17+
bytes32 messageHash;
18+
bytes sig;
19+
}
20+
}
21+
22+
interface IECDSACertificateVerifierEvents is IECDSCertificateVerifierTypes {
23+
/// @notice Emitted when a table is updated
24+
event TableUpdated(uint32 referenceTimestamp, ECDSAOperatorInfo[] operatorInfos);
25+
}
26+
27+
/// @notice A base table manager interface that handles operator table updates
28+
/// @dev We separate out this interface for forwards-compatibility with a future `TableManager` contract that stores all operatorSet's tables on a chain
29+
interface IECDSATableManager is IECDSCertificateVerifierTypes {
30+
/**
31+
* @notice updates the operator table
32+
* @param operatorSet the operatorSet to update the operator table for
33+
* @param referenceTimestamp the timestamp at which the operatorInfos were sourced
34+
* @param operatorInfos the operatorInfos to update the operator table with
35+
* @dev only callable by the operatorTableUpdater
36+
* @dev We pass in an `operatorSet` for future-proofing a global `TableManager` contract
37+
*/
38+
function updateOperatorTable(
39+
OperatorSet calldata operatorSet,
40+
uint32 referenceTimestamp,
41+
ECDSAOperatorInfo[] calldata operatorInfos
42+
) external;
43+
44+
/**
45+
* @notice ejects operators from the operatorSet
46+
* @param operatorSet the operatorSet to eject operators from
47+
* @param referenceTimestamp the timestamp of the operator table against which
48+
* the ejection is being done
49+
* @param operatorIndices the indices of the operators to eject
50+
* @dev only callable by the ejector
51+
* @dev We pass in an `operatorSet` for future-proofing a global `TableManager` contract
52+
*/
53+
function ejectOperators(
54+
OperatorSet calldata operatorSet,
55+
uint32 referenceTimestamp,
56+
uint32[] calldata operatorIndices
57+
) external;
58+
}
59+
60+
interface IECDSACertificateVerifier is
61+
ICertificateVerifier,
62+
IECDSATableManager,
63+
IECDSACertificateVerifierEvents
64+
{
65+
/**
66+
* @notice verifies a certificate
67+
* @param cert a certificate
68+
* @return signedStakes amount of stake that signed the certificate for each stake
69+
* type
70+
*/
71+
function verifyCertificate(
72+
ECDSACertificate memory cert
73+
) external returns (uint96[] memory signedStakes);
74+
75+
/**
76+
* @notice verifies a certificate and makes sure that the signed stakes meet
77+
* provided portions of the total stake on the AVS
78+
* @param cert a certificate
79+
* @param totalStakeProportionThresholds the proportion of total stake that
80+
* the signed stake of the certificate should meet
81+
* @return whether or not certificate is valid and meets thresholds
82+
*/
83+
function verifyCertificateProportion(
84+
ECDSACertificate memory cert,
85+
uint16[] memory totalStakeProportionThresholds
86+
) external returns (bool);
87+
88+
/**
89+
* @notice verifies a certificate and makes sure that the signed stakes meet
90+
* provided portions of the total stake on the AVS
91+
* @param cert a certificate
92+
* @param totalStakeNominalThresholds the proportion of total stake that
93+
* the signed stake of the certificate should meet
94+
* @return whether or not certificate is valid and meets thresholds
95+
*/
96+
function verifyCertificateNominal(
97+
ECDSACertificate memory cert,
98+
uint96[] memory totalStakeNominalThresholds
99+
) external returns (bool);
100+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
5+
import {IOperatorTableCalculator} from "./IOperatorTableCalculator.sol";
6+
7+
interface IECDSATableCalculatorTypes {
8+
/**
9+
* @notice A struct that contains information about a single operator
10+
* @param pubkey The address of the operator
11+
* @param weights The weights of the operator for a single operatorSet
12+
* @dev The `weights` array can be defined as a list of arbitrary groupings. For example,
13+
* it can be [slashable_stake, delegated_stake, strategy_i_stake, ...]
14+
*/
15+
struct ECDSAOperatorInfo {
16+
address pubkey;
17+
uint96[] weights;
18+
}
19+
}
20+
21+
interface IECDSATableCalculator is IOperatorTableCalculator, IECDSATableCalculatorTypes {
22+
/**
23+
* @notice calculates the operatorInfos for a given operatorSet
24+
* @param operatorSet the operatorSet to calculate the operator table for
25+
* @return operatorInfos the list of operatorInfos for the given operatorSet
26+
* @dev The output of this function is converted to bytes via the `calculateOperatorTableBytes` function
27+
*/
28+
function calculateOperatorTable(
29+
OperatorSet calldata operatorSet
30+
) external view returns (ECDSAOperatorInfo[] memory operatorInfos);
31+
}

0 commit comments

Comments
 (0)