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
2 changes: 1 addition & 1 deletion lib/eigenlayer-contracts
Submodule eigenlayer-contracts updated 53 files
+2 −2 pkg/bindings/BN254CertificateVerifier/binding.go
+1 −1 pkg/bindings/BN254CertificateVerifierStorage/binding.go
+1 −1 pkg/bindings/BN254TableCalculator/binding.go
+1 −1 pkg/bindings/CrossChainRegistry/binding.go
+2 −2 pkg/bindings/ECDSACertificateVerifier/binding.go
+1 −1 pkg/bindings/ECDSACertificateVerifierStorage/binding.go
+1 −1 pkg/bindings/ECDSATableCalculator/binding.go
+1 −1 pkg/bindings/IBN254CertificateVerifier/binding.go
+1 −1 pkg/bindings/IBaseCertificateVerifier/binding.go
+1 −1 pkg/bindings/IECDSACertificateVerifier/binding.go
+1 −1 pkg/bindings/IKeyRegistrar/binding.go
+263 −1 pkg/bindings/IOperatorTableUpdater/binding.go
+2 −2 pkg/bindings/KeyRegistrar/binding.go
+1 −1 pkg/bindings/KeyRegistrarStorage/binding.go
+250 −2 pkg/bindings/OperatorTableUpdater/binding.go
+263 −1 pkg/bindings/OperatorTableUpdaterStorage/binding.go
+0 −150 script/deploy/devnet/mutlichain/deploy_globalRootConfirmerSet.s.sol
+0 −115 script/deploy/devnet/mutlichain/deploy_multichain_l1.s.sol
+0 −170 script/deploy/devnet/mutlichain/deploy_multichain_l2.s.sol
+0 −5 script/utils/ExistingDeploymentParser.sol
+2 −2 src/contracts/interfaces/IBN254CertificateVerifier.sol
+0 −62 src/contracts/interfaces/IBN254TableCalculator.sol
+2 −0 src/contracts/interfaces/IBaseCertificateVerifier.sol
+2 −2 src/contracts/interfaces/IECDSACertificateVerifier.sol
+0 −47 src/contracts/interfaces/IECDSATableCalculator.sol
+52 −0 src/contracts/interfaces/IOperatorTableCalculator.sol
+51 −3 src/contracts/interfaces/IOperatorTableUpdater.sol
+3 −0 src/contracts/multichain/BN254CertificateVerifier.sol
+0 −1 src/contracts/multichain/BN254CertificateVerifierStorage.sol
+0 −79 src/contracts/multichain/BN254TableCalculator.sol
+0 −180 src/contracts/multichain/BN254TableCalculatorBase.sol
+3 −0 src/contracts/multichain/ECDSACertificateVerifier.sol
+0 −1 src/contracts/multichain/ECDSACertificateVerifierStorage.sol
+0 −79 src/contracts/multichain/ECDSATableCalculator.sol
+0 −127 src/contracts/multichain/ECDSATableCalculatorBase.sol
+55 −5 src/contracts/multichain/OperatorTableUpdater.sol
+4 −1 src/contracts/multichain/OperatorTableUpdaterStorage.sol
+22 −22 src/contracts/permissions/KeyRegistrar.sol
+3 −3 src/contracts/permissions/KeyRegistrarStorage.sol
+0 −2 src/test/integration/IntegrationDeployer.t.sol
+0 −324 src/test/integration/tests/multichain/BN254OperatorSet_CalculateWeights.t.sol
+11 −0 src/test/mocks/OperatorTableUpdaterMock.sol
+0 −31 src/test/tree/BN254TableCalculatorBase.tree
+0 −34 src/test/tree/ECDSATableCalculatorBase.tree
+115 −0 src/test/tree/KeyRegistrar.tree
+19 −1 src/test/tree/OperatorTableUpdaterUnit.tree
+14 −1 src/test/unit/BN254CertificateVerifierUnit.t.sol
+0 −694 src/test/unit/BN254TableCalculatorBaseUnit.t.sol
+13 −0 src/test/unit/ECDSACertificateVerifierUnit.t.sol
+0 −742 src/test/unit/ECDSATableCalculatorBaseUnit.t.sol
+599 −435 src/test/unit/KeyRegistrarUnit.t.sol
+892 −0 src/test/unit/Old.t.sol
+260 −7 src/test/unit/OperatorTableUpdaterUnit.t.sol
29 changes: 29 additions & 0 deletions src/interfaces/IBN254TableCalculator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
import {
IOperatorTableCalculator,
IOperatorTableCalculatorTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IOperatorTableCalculator.sol";

interface IBN254TableCalculator is IOperatorTableCalculator, IOperatorTableCalculatorTypes {
/**
* @notice calculates the operatorInfos for a given operatorSet
* @param operatorSet the operatorSet to calculate the operator table for
* @return operatorSetInfo the operatorSetInfo for the given operatorSet
* @dev The output of this function is converted to bytes via the `calculateOperatorTableBytes` function
*/
function calculateOperatorTable(
OperatorSet calldata operatorSet
) external view returns (BN254OperatorSetInfo memory operatorSetInfo);

/**
* @notice Get the operatorInfos for a given operatorSet
* @param operatorSet the operatorSet to get the operatorInfos for
* @return operatorInfos the operatorInfos for the given operatorSet
*/
function getOperatorInfos(
OperatorSet calldata operatorSet
) external view returns (BN254OperatorInfo[] memory operatorInfos);
}
20 changes: 20 additions & 0 deletions src/interfaces/IECDSATableCalculator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
import {
IOperatorTableCalculator,
IOperatorTableCalculatorTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IOperatorTableCalculator.sol";

interface IECDSATableCalculator is IOperatorTableCalculator, IOperatorTableCalculatorTypes {
/**
* @notice calculates the operatorInfos for a given operatorSet
* @param operatorSet the operatorSet to calculate the operator table for
* @return operatorInfos the list of operatorInfos for the given operatorSet
* @dev The output of this function is converted to bytes via the `calculateOperatorTableBytes` function
*/
function calculateOperatorTable(
OperatorSet calldata operatorSet
) external view returns (ECDSAOperatorInfo[] memory operatorInfos);
}
84 changes: 84 additions & 0 deletions src/middlewareV2/tableCalculator/BN254TableCalculator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;

import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
import {IAllocationManager} from
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {IKeyRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IKeyRegistrar.sol";

import "./BN254TableCalculatorBase.sol";

/**
* @title BN254TableCalculator
* @notice Implementation that calculates BN254 operator tables using the sum of the minimum slashable stake weights
*/
contract BN254TableCalculator is BN254TableCalculatorBase {
// Immutables
/// @notice AllocationManager contract for managing operator allocations
IAllocationManager public immutable allocationManager;
/// @notice The default lookahead blocks for the slashable stake lookup
uint256 public immutable LOOKAHEAD_BLOCKS;

constructor(
IKeyRegistrar _keyRegistrar,
IAllocationManager _allocationManager,
uint256 _LOOKAHEAD_BLOCKS
) BN254TableCalculatorBase(_keyRegistrar) {
allocationManager = _allocationManager;
LOOKAHEAD_BLOCKS = _LOOKAHEAD_BLOCKS;
}

/**
* @notice Get the operator weights for a given operatorSet based on the slashable stake.
* @param operatorSet The operatorSet to get the weights for
* @return operators The addresses of the operators in the operatorSet
* @return weights The weights for each operator in the operatorSet, this is a 2D array where the first index is the operator
* and the second index is the type of weight. In this case its of length 1 and returns the slashable stake for the operatorSet.
*/
function _getOperatorWeights(
OperatorSet calldata operatorSet
) internal view override returns (address[] memory operators, uint256[][] memory weights) {
// Get all operators & strategies in the operatorSet
address[] memory registeredOperators = allocationManager.getMembers(operatorSet);
IStrategy[] memory strategies = allocationManager.getStrategiesInOperatorSet(operatorSet);

// Get the minimum slashable stake for each operator
uint256[][] memory minSlashableStake = allocationManager.getMinimumSlashableStake({
operatorSet: operatorSet,
operators: registeredOperators,
strategies: strategies,
futureBlock: uint32(block.number + LOOKAHEAD_BLOCKS)
});

operators = new address[](registeredOperators.length);
weights = new uint256[][](registeredOperators.length);
uint256 operatorCount = 0;
for (uint256 i = 0; i < registeredOperators.length; ++i) {
// For the given operator, loop through the strategies and sum together to calculate the operator's weight for the operatorSet
uint256 totalWeight;
for (uint256 stratIndex = 0; stratIndex < strategies.length; ++stratIndex) {
totalWeight += minSlashableStake[i][stratIndex];
}

// If the operator has nonzero slashable stake, add them to the operators array
if (totalWeight > 0) {
// Initialize operator weights array of length 1 just for slashable stake
weights[operatorCount] = new uint256[](1);
weights[operatorCount][0] = totalWeight;

// Add the operator to the operators array
operators[operatorCount] = registeredOperators[i];
operatorCount++;
}
}

// Resize arrays to be the size of the number of operators with nonzero slashable stake
assembly {
mstore(operators, operatorCount)
mstore(weights, operatorCount)
}

return (operators, weights);
}
}
184 changes: 184 additions & 0 deletions src/middlewareV2/tableCalculator/BN254TableCalculatorBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;

import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
import {IOperatorTableCalculator} from
"eigenlayer-contracts/src/contracts/interfaces/IOperatorTableCalculator.sol";
import {IKeyRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IKeyRegistrar.sol";
import {Merkle} from "eigenlayer-contracts/src/contracts/libraries/Merkle.sol";
import {BN254} from "eigenlayer-contracts/src/contracts/libraries/BN254.sol";
import {IBN254TableCalculator} from "../../interfaces/IBN254TableCalculator.sol";

/**
* @title BN254TableCalculatorBase
* @notice Abstract contract that provides base functionality for calculating BN254 operator tables
* @dev This contract contains all the core logic for operator table calculations,
* with weight calculation left to be implemented by derived contracts
*/
abstract contract BN254TableCalculatorBase is IBN254TableCalculator {
using Merkle for bytes32[];
using BN254 for BN254.G1Point;

// Immutables
/// @notice KeyRegistrar contract for managing operator keys
IKeyRegistrar public immutable keyRegistrar;

constructor(
IKeyRegistrar _keyRegistrar
) {
keyRegistrar = _keyRegistrar;
}

/// @inheritdoc IBN254TableCalculator
function calculateOperatorTable(
OperatorSet calldata operatorSet
) external view virtual returns (BN254OperatorSetInfo memory operatorSetInfo) {
return _calculateOperatorTable(operatorSet);
}

/// @inheritdoc IOperatorTableCalculator
function calculateOperatorTableBytes(
OperatorSet calldata operatorSet
) external view virtual returns (bytes memory operatorTableBytes) {
return abi.encode(_calculateOperatorTable(operatorSet));
}

/// @inheritdoc IOperatorTableCalculator
function getOperatorWeights(
OperatorSet calldata operatorSet
) external view virtual returns (address[] memory operators, uint256[][] memory weights) {
return _getOperatorWeights(operatorSet);
}

/// @inheritdoc IOperatorTableCalculator
function getOperatorWeight(
OperatorSet calldata operatorSet,
address operator
) external view virtual returns (uint256 weight) {
(address[] memory operators, uint256[][] memory weights) = _getOperatorWeights(operatorSet);

// Find the index of the operator in the operators array
for (uint256 i = 0; i < operators.length; i++) {
if (operators[i] == operator) {
return weights[i][0];
}
}

return 0;
}

/// @inheritdoc IBN254TableCalculator
function getOperatorInfos(
OperatorSet calldata operatorSet
) external view virtual returns (BN254OperatorInfo[] memory) {
// Get the weights for all operators
(address[] memory operators, uint256[][] memory weights) = _getOperatorWeights(operatorSet);

BN254OperatorInfo[] memory operatorInfos = new BN254OperatorInfo[](operators.length);

for (uint256 i = 0; i < operators.length; i++) {
// Skip if the operator has not registered their key
if (!keyRegistrar.isRegistered(operatorSet, operators[i])) {
continue;
}

(BN254.G1Point memory g1Point,) = keyRegistrar.getBN254Key(operatorSet, operators[i]);
operatorInfos[i] = BN254OperatorInfo({pubkey: g1Point, weights: weights[i]});
}

return operatorInfos;
}

/**
* @notice Abstract function to get the operator weights for a given operatorSet
* @param operatorSet The operatorSet to get the weights for
* @return operators The addresses of the operators in the operatorSet
* @return weights The weights for each operator in the operatorSet, this is a 2D array where the first index is the operator
* and the second index is the type of weight
* @dev Must be implemented by derived contracts to define specific weight calculation logic
*/
function _getOperatorWeights(
OperatorSet calldata operatorSet
) internal view virtual returns (address[] memory operators, uint256[][] memory weights);

/**
* @notice Calculates the operator table for a given operatorSet, also calculates the aggregate pubkey for the operatorSet
* @param operatorSet The operatorSet to calculate the operator table for
* @return operatorSetInfo The operator table for the given operatorSet
* @dev This function:
* 1. Gets operator weights from the weight calculator
* 2. Collates weights into total weights
* 3. Creates a merkle tree of operator info
* - assumes that the operator has a registered BN254 key
* 4. Calculates the aggregate public key
*/
function _calculateOperatorTable(
OperatorSet calldata operatorSet
) internal view returns (BN254OperatorSetInfo memory operatorSetInfo) {
// Get the weights for all operators in the operatorSet
(address[] memory operators, uint256[][] memory weights) = _getOperatorWeights(operatorSet);

// If there are no weights, return an empty operator set info
if (weights.length == 0) {
return BN254OperatorSetInfo({
operatorInfoTreeRoot: bytes32(0),
numOperators: 0,
aggregatePubkey: BN254.G1Point(0, 0),
totalWeights: new uint256[](0)
});
}

// Initialize arrays
uint256 subArrayLength = weights[0].length;
uint256[] memory totalWeights = new uint256[](subArrayLength);
bytes32[] memory operatorInfoLeaves = new bytes32[](operators.length);
BN254.G1Point memory aggregatePubkey;
uint256 operatorCount = 0;

for (uint256 i = 0; i < operators.length; i++) {
// Skip if the operator has not registered their key
if (!keyRegistrar.isRegistered(operatorSet, operators[i])) {
continue;
}

// Read the weights for the operator and encode them into the operatorInfoLeaves
// for all weights, add them to the total weights. The ith index returns the weights array for the ith operator
for (uint256 j = 0; j < subArrayLength; j++) {
totalWeights[j] += weights[i][j];
}
(BN254.G1Point memory g1Point,) = keyRegistrar.getBN254Key(operatorSet, operators[i]);
operatorInfoLeaves[i] =
keccak256(abi.encode(BN254OperatorInfo({pubkey: g1Point, weights: weights[i]})));

// Add the operator's G1 point to the aggregate pubkey
aggregatePubkey = aggregatePubkey.plus(g1Point);

// Increment the operator count
operatorCount++;
}

// If there are no operators, return an empty operator set info
if (operatorCount == 0) {
return BN254OperatorSetInfo({
operatorInfoTreeRoot: bytes32(0),
numOperators: 0,
aggregatePubkey: BN254.G1Point(0, 0),
totalWeights: new uint256[](0)
});
}

// Resize the operatorInfoLeaves array to the number of operators and merkleize
assembly {
mstore(operatorInfoLeaves, operatorCount)
}

bytes32 operatorInfoTreeRoot = operatorInfoLeaves.merkleizeKeccak();

return BN254OperatorSetInfo({
operatorInfoTreeRoot: operatorInfoTreeRoot,
numOperators: operatorCount,
aggregatePubkey: aggregatePubkey,
totalWeights: totalWeights
});
}
}
Loading
Loading