-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AVS-215, AVS-259: Add Subgraphs #233
Merged
Changes from 10 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
b66c56d
added querier
Sidu28 fb2886e
added grahql query
Sidu28 ecfedbb
cleanup
Sidu28 9ff18c2
added optimistic test
Sidu28 079f1e0
AVS-259: Subgraph test (#244)
Sidu28 9a80d5c
Subgraph testing (#245)
Sidu28 9b8b4be
resolved merge
Sidu28 48f51eb
added remappings
Sidu28 7dc8a2f
integration test
Sidu28 5183a39
added integration test halpers
Sidu28 f6569c3
fixed
Sidu28 5667b64
cleaned gir modules
Sidu28 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
[submodule "contracts/lib/eigenlayer-middleware"] | ||
path = contracts/lib/eigenlayer-middleware | ||
url = [email protected]:Layr-Labs/eigenlayer-middleware.git | ||
[submodule "services/operatorsinfo/integration_test_deployment/lib/forge-std"] | ||
path = services/operatorsinfo/integration_test_deployment/lib/forge-std | ||
url = https://github.com/foundry-rs/forge-std | ||
[submodule "services/operatorsinfo/integration_test_deployment/lib/eigenlayer-middleware"] | ||
path = services/operatorsinfo/integration_test_deployment/lib/eigenlayer-middleware | ||
url = https://github.com/Layr-Labs/eigenlayer-middleware | ||
[submodule "services/operatorsinfo/integration_test_deployment/lib/eigenlayer-middleware-offchain"] | ||
path = services/operatorsinfo/integration_test_deployment/lib/eigenlayer-middleware-offchain | ||
url = https://github.com/Layr-Labs/eigenlayer-middleware-offchain | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
services/operatorsinfo/integration_test_deployment/.github/workflows/test.yml
samlaf marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: test | ||
|
||
on: workflow_dispatch | ||
|
||
env: | ||
FOUNDRY_PROFILE: ci | ||
|
||
jobs: | ||
check: | ||
strategy: | ||
fail-fast: true | ||
|
||
name: Foundry project | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
with: | ||
submodules: recursive | ||
|
||
- name: Install Foundry | ||
uses: foundry-rs/foundry-toolchain@v1 | ||
with: | ||
version: nightly | ||
|
||
- name: Run Forge build | ||
run: | | ||
forge --version | ||
forge build --sizes | ||
id: build | ||
|
||
- name: Run Forge tests | ||
run: | | ||
forge test -vvv | ||
id: test |
14 changes: 14 additions & 0 deletions
14
services/operatorsinfo/integration_test_deployment/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Compiler files | ||
cache/ | ||
out/ | ||
|
||
# Ignores development broadcast logs | ||
!/broadcast | ||
/broadcast/*/31337/ | ||
/broadcast/**/dry-run/ | ||
|
||
# Docs | ||
docs/ | ||
|
||
# Dotenv file | ||
.env |
284 changes: 284 additions & 0 deletions
284
services/operatorsinfo/integration_test_deployment/BLSApkRegistryMock.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
import {BLSApkRegistryStorage} from "../../contracts/lib/eigenlayer-middleware/src/BLSApkRegistryStorage.sol"; | ||
|
||
import {IRegistryCoordinator} from "../../contracts/lib/eigenlayer-middleware/src/interfaces/IRegistryCoordinator.sol"; | ||
|
||
import {BN254} from "../../contracts/lib/eigenlayer-middleware/src/libraries/BN254.sol"; | ||
|
||
contract BLSApkRegistryMock is BLSApkRegistryStorage { | ||
using BN254 for BN254.G1Point; | ||
|
||
/// @notice when applied to a function, only allows the RegistryCoordinator to call it | ||
modifier onlyRegistryCoordinator() { | ||
require( | ||
msg.sender == address(registryCoordinator), | ||
"BLSApkRegistry.onlyRegistryCoordinator: caller is not the registry coordinator" | ||
); | ||
_; | ||
} | ||
|
||
/// @notice Sets the (immutable) `registryCoordinator` address | ||
constructor( | ||
IRegistryCoordinator _registryCoordinator | ||
) BLSApkRegistryStorage(_registryCoordinator) {} | ||
|
||
/******************************************************************************* | ||
EXTERNAL FUNCTIONS - REGISTRY COORDINATOR | ||
*******************************************************************************/ | ||
|
||
/** | ||
* @notice Registers the `operator`'s pubkey for the specified `quorumNumbers`. | ||
* @param operator The address of the operator to register. | ||
* @param quorumNumbers The quorum numbers the operator is registering for, where each byte is an 8 bit integer quorumNumber. | ||
* @dev access restricted to the RegistryCoordinator | ||
* @dev Preconditions (these are assumed, not validated in this contract): | ||
* 1) `quorumNumbers` has no duplicates | ||
* 2) `quorumNumbers.length` != 0 | ||
* 3) `quorumNumbers` is ordered in ascending order | ||
* 4) the operator is not already registered | ||
*/ | ||
function registerOperator( | ||
address operator, | ||
bytes memory quorumNumbers | ||
) public virtual onlyRegistryCoordinator { | ||
// Get the operator's pubkey. Reverts if they have not registered a key | ||
(BN254.G1Point memory pubkey, ) = getRegisteredPubkey(operator); | ||
|
||
// Update each quorum's aggregate pubkey | ||
_processQuorumApkUpdate(quorumNumbers, pubkey); | ||
|
||
// Return pubkeyHash, which will become the operator's unique id | ||
emit OperatorAddedToQuorums(operator, getOperatorId(operator), quorumNumbers); | ||
} | ||
|
||
/** | ||
* @notice Deregisters the `operator`'s pubkey for the specified `quorumNumbers`. | ||
* @param operator The address of the operator to deregister. | ||
* @param quorumNumbers The quorum numbers the operator is deregistering from, where each byte is an 8 bit integer quorumNumber. | ||
* @dev access restricted to the RegistryCoordinator | ||
* @dev Preconditions (these are assumed, not validated in this contract): | ||
* 1) `quorumNumbers` has no duplicates | ||
* 2) `quorumNumbers.length` != 0 | ||
* 3) `quorumNumbers` is ordered in ascending order | ||
* 4) the operator is not already deregistered | ||
* 5) `quorumNumbers` is a subset of the quorumNumbers that the operator is registered for | ||
*/ | ||
function deregisterOperator( | ||
address operator, | ||
bytes memory quorumNumbers | ||
) public virtual onlyRegistryCoordinator { | ||
// Get the operator's pubkey. Reverts if they have not registered a key | ||
(BN254.G1Point memory pubkey, ) = getRegisteredPubkey(operator); | ||
|
||
// Update each quorum's aggregate pubkey | ||
_processQuorumApkUpdate(quorumNumbers, pubkey.negate()); | ||
emit OperatorRemovedFromQuorums(operator, getOperatorId(operator), quorumNumbers); | ||
} | ||
|
||
/** | ||
* @notice Initializes a new quorum by pushing its first apk update | ||
* @param quorumNumber The number of the new quorum | ||
*/ | ||
function initializeQuorum(uint8 quorumNumber) public virtual onlyRegistryCoordinator { | ||
require(apkHistory[quorumNumber].length == 0, "BLSApkRegistry.initializeQuorum: quorum already exists"); | ||
|
||
apkHistory[quorumNumber].push(ApkUpdate({ | ||
apkHash: bytes24(0), | ||
updateBlockNumber: uint32(block.number), | ||
nextUpdateBlockNumber: 0 | ||
})); | ||
} | ||
|
||
/** | ||
* @notice Called by the RegistryCoordinator register an operator as the owner of a BLS public key. | ||
* @param operator is the operator for whom the key is being registered | ||
* @param params contains the G1 & G2 public keys of the operator, and a signature proving their ownership | ||
* @param pubkeyRegistrationMessageHash is a hash that the operator must sign to prove key ownership | ||
*/ | ||
function registerBLSPublicKey( | ||
address operator, | ||
PubkeyRegistrationParams calldata params, | ||
BN254.G1Point calldata pubkeyRegistrationMessageHash | ||
) external returns (bytes32 operatorId) { | ||
bytes32 pubkeyHash = BN254.hashG1Point(params.pubkeyG1); | ||
require( | ||
pubkeyHash != ZERO_PK_HASH, "BLSApkRegistry.registerBLSPublicKey: cannot register zero pubkey" | ||
); | ||
require( | ||
operatorToPubkeyHash[operator] == bytes32(0), | ||
"BLSApkRegistry.registerBLSPublicKey: operator already registered pubkey" | ||
); | ||
require( | ||
pubkeyHashToOperator[pubkeyHash] == address(0), | ||
"BLSApkRegistry.registerBLSPublicKey: public key already registered" | ||
); | ||
|
||
// gamma = h(sigma, P, P', H(m)) | ||
uint256 gamma = uint256(keccak256(abi.encodePacked( | ||
params.pubkeyRegistrationSignature.X, | ||
params.pubkeyRegistrationSignature.Y, | ||
params.pubkeyG1.X, | ||
params.pubkeyG1.Y, | ||
params.pubkeyG2.X, | ||
params.pubkeyG2.Y, | ||
pubkeyRegistrationMessageHash.X, | ||
pubkeyRegistrationMessageHash.Y | ||
))) % BN254.FR_MODULUS; | ||
|
||
// e(sigma + P * gamma, [-1]_2) = e(H(m) + [1]_1 * gamma, P') | ||
require(BN254.pairing( | ||
params.pubkeyRegistrationSignature.plus(params.pubkeyG1.scalar_mul(gamma)), | ||
BN254.negGeneratorG2(), | ||
pubkeyRegistrationMessageHash.plus(BN254.generatorG1().scalar_mul(gamma)), | ||
params.pubkeyG2 | ||
), "BLSApkRegistry.registerBLSPublicKey: either the G1 signature is wrong, or G1 and G2 private key do not match"); | ||
|
||
operatorToPubkey[operator] = params.pubkeyG1; | ||
operatorToPubkeyHash[operator] = pubkeyHash; | ||
pubkeyHashToOperator[pubkeyHash] = operator; | ||
|
||
emit NewPubkeyRegistration(operator, params.pubkeyG1, params.pubkeyG2); | ||
return pubkeyHash; | ||
} | ||
|
||
/******************************************************************************* | ||
INTERNAL FUNCTIONS | ||
*******************************************************************************/ | ||
|
||
function _processQuorumApkUpdate(bytes memory quorumNumbers, BN254.G1Point memory point) internal { | ||
BN254.G1Point memory newApk; | ||
|
||
for (uint256 i = 0; i < quorumNumbers.length; i++) { | ||
// Validate quorum exists and get history length | ||
uint8 quorumNumber = uint8(quorumNumbers[i]); | ||
uint256 historyLength = apkHistory[quorumNumber].length; | ||
require(historyLength != 0, "BLSApkRegistry._processQuorumApkUpdate: quorum does not exist"); | ||
|
||
// Update aggregate public key for this quorum | ||
newApk = currentApk[quorumNumber].plus(point); | ||
currentApk[quorumNumber] = newApk; | ||
bytes24 newApkHash = bytes24(BN254.hashG1Point(newApk)); | ||
|
||
// Update apk history. If the last update was made in this block, update the entry | ||
// Otherwise, push a new historical entry and update the prev->next pointer | ||
ApkUpdate storage lastUpdate = apkHistory[quorumNumber][historyLength - 1]; | ||
if (lastUpdate.updateBlockNumber == uint32(block.number)) { | ||
lastUpdate.apkHash = newApkHash; | ||
} else { | ||
lastUpdate.nextUpdateBlockNumber = uint32(block.number); | ||
apkHistory[quorumNumber].push(ApkUpdate({ | ||
apkHash: newApkHash, | ||
updateBlockNumber: uint32(block.number), | ||
nextUpdateBlockNumber: 0 | ||
})); | ||
} | ||
} | ||
} | ||
|
||
/******************************************************************************* | ||
VIEW FUNCTIONS | ||
*******************************************************************************/ | ||
/** | ||
* @notice Returns the pubkey and pubkey hash of an operator | ||
* @dev Reverts if the operator has not registered a valid pubkey | ||
*/ | ||
function getRegisteredPubkey(address operator) public view returns (BN254.G1Point memory, bytes32) { | ||
BN254.G1Point memory pubkey = operatorToPubkey[operator]; | ||
bytes32 pubkeyHash = operatorToPubkeyHash[operator]; | ||
|
||
require( | ||
pubkeyHash != bytes32(0), | ||
"BLSApkRegistry.getRegisteredPubkey: operator is not registered" | ||
); | ||
|
||
return (pubkey, pubkeyHash); | ||
} | ||
|
||
/** | ||
* @notice Returns the indices of the quorumApks index at `blockNumber` for the provided `quorumNumbers` | ||
* @dev Returns the current indices if `blockNumber >= block.number` | ||
*/ | ||
function getApkIndicesAtBlockNumber( | ||
bytes calldata quorumNumbers, | ||
uint256 blockNumber | ||
) external view returns (uint32[] memory) { | ||
uint32[] memory indices = new uint32[](quorumNumbers.length); | ||
|
||
for (uint256 i = 0; i < quorumNumbers.length; i++) { | ||
uint8 quorumNumber = uint8(quorumNumbers[i]); | ||
|
||
uint256 quorumApkUpdatesLength = apkHistory[quorumNumber].length; | ||
if (quorumApkUpdatesLength == 0 || blockNumber < apkHistory[quorumNumber][0].updateBlockNumber) { | ||
revert("BLSApkRegistry.getApkIndicesAtBlockNumber: blockNumber is before the first update"); | ||
} | ||
|
||
// Loop backward through apkHistory until we find an entry that preceeds `blockNumber` | ||
for (uint256 j = quorumApkUpdatesLength; j > 0; j--) { | ||
if (apkHistory[quorumNumber][j - 1].updateBlockNumber <= blockNumber) { | ||
indices[i] = uint32(j - 1); | ||
break; | ||
} | ||
} | ||
} | ||
return indices; | ||
} | ||
|
||
/// @notice Returns the current APK for the provided `quorumNumber ` | ||
function getApk(uint8 quorumNumber) external view returns (BN254.G1Point memory) { | ||
return currentApk[quorumNumber]; | ||
} | ||
|
||
/// @notice Returns the `ApkUpdate` struct at `index` in the list of APK updates for the `quorumNumber` | ||
function getApkUpdateAtIndex(uint8 quorumNumber, uint256 index) external view returns (ApkUpdate memory) { | ||
return apkHistory[quorumNumber][index]; | ||
} | ||
|
||
/** | ||
* @notice get hash of the apk of `quorumNumber` at `blockNumber` using the provided `index`; | ||
* called by checkSignatures in BLSSignatureChecker.sol. | ||
* @param quorumNumber is the quorum whose ApkHash is being retrieved | ||
* @param blockNumber is the number of the block for which the latest ApkHash will be retrieved | ||
* @param index is the index of the apkUpdate being retrieved from the list of quorum apkUpdates in storage | ||
*/ | ||
function getApkHashAtBlockNumberAndIndex( | ||
uint8 quorumNumber, | ||
uint32 blockNumber, | ||
uint256 index | ||
) external view returns (bytes24) { | ||
ApkUpdate memory quorumApkUpdate = apkHistory[quorumNumber][index]; | ||
|
||
/** | ||
* Validate that the update is valid for the given blockNumber: | ||
* - blockNumber should be >= the update block number | ||
* - the next update block number should be either 0 or strictly greater than blockNumber | ||
*/ | ||
require( | ||
blockNumber >= quorumApkUpdate.updateBlockNumber, | ||
"BLSApkRegistry._validateApkHashAtBlockNumber: index too recent" | ||
); | ||
require( | ||
quorumApkUpdate.nextUpdateBlockNumber == 0 || blockNumber < quorumApkUpdate.nextUpdateBlockNumber, | ||
"BLSApkRegistry._validateApkHashAtBlockNumber: not latest apk update" | ||
); | ||
|
||
return quorumApkUpdate.apkHash; | ||
} | ||
|
||
/// @notice Returns the length of ApkUpdates for the provided `quorumNumber` | ||
function getApkHistoryLength(uint8 quorumNumber) external view returns (uint32) { | ||
return uint32(apkHistory[quorumNumber].length); | ||
} | ||
|
||
/// @notice Returns the operator address for the given `pubkeyHash` | ||
function getOperatorFromPubkeyHash(bytes32 pubkeyHash) public view returns (address) { | ||
return pubkeyHashToOperator[pubkeyHash]; | ||
} | ||
|
||
/// @notice returns the ID used to identify the `operator` within this AVS | ||
/// @dev Returns zero in the event that the `operator` has never registered for the AVS | ||
function getOperatorId(address operator) public view returns (bytes32) { | ||
return operatorToPubkeyHash[operator]; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these still needed? don't think they are used anymore after the last commit that deleted a bunch of stuff?