Skip to content
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

test: admin functions #131

Merged
merged 1 commit into from
May 13, 2024
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
6 changes: 3 additions & 3 deletions contracts/test/AVSDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ contract AVSDeployer is Test {
/// @notice StakeRegistry, Constant used as a divisor in calculating weights.
uint256 public constant WEIGHTING_DIVISOR = 1e18;

address public proxyAdminOwner = address(uint160(uint256(keccak256("proxyAdminOwner"))));
address public proxyAdminOwner = 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38;
address public registryCoordinatorOwner = address(uint160(uint256(keccak256("registryCoordinatorOwner"))));
address public pauser = address(uint160(uint256(keccak256("pauser"))));
address public unpauser = address(uint160(uint256(keccak256("unpauser"))));
Expand All @@ -100,12 +100,12 @@ contract AVSDeployer is Test {
uint32 defaultMaxOperatorCount = 10;
uint16 defaultKickBIPsOfOperatorStake = 15000;
uint16 defaultKickBIPsOfTotalStake = 150;
uint8 numQuorums = 192;
uint8 numQuorums = 1;

IRegistryCoordinator.OperatorSetParam[] operatorSetParams;

uint8 maxQuorumsToRegisterFor = 4;
uint256 maxOperatorsToRegister = 4;
uint256 maxOperatorsToRegister = 10;
uint32 registrationBlockNumber = 100;
uint32 blocksBetweenRegistrations = 10;

Expand Down
164 changes: 164 additions & 0 deletions contracts/test/BLSAVSDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;

import {BLSSignatureChecker} from "eigenlayer-middleware/BLSSignatureChecker.sol";
import {BN254} from "eigenlayer-middleware/libraries/BN254.sol";
import {OperatorStateRetriever} from "eigenlayer-middleware/OperatorStateRetriever.sol";
import {BitmapUtils} from "eigenlayer-middleware/libraries/BitmapUtils.sol";
import {AVSDeployer} from "./AVSDeployer.sol";

contract BLSAVSDeployer is AVSDeployer {
using BN254 for BN254.G1Point;

bytes32 msgHash;
uint256 aggSignerPrivKey = 69;
BN254.G2Point aggSignerApkG2;
BN254.G2Point oneHundredQuorumApkG2;
BN254.G1Point sigma;

function _setUpBLSMockAVSDeployer() public virtual {
_deployMockEigenLayerAndAVS();
_setAggregatePublicKeysAndSignature();
}

function _setUpBLSMockAVSDeployer(uint8 numQuorumsToAdd) public virtual {
_deployMockEigenLayerAndAVS(numQuorumsToAdd);
_setAggregatePublicKeysAndSignature();
}

function _setAggregatePublicKeysAndSignature() internal {
// aggSignerPrivKey*g2
aggSignerApkG2.X[1] = 19101821850089705274637533855249918363070101489527618151493230256975900223847;
aggSignerApkG2.X[0] = 5334410886741819556325359147377682006012228123419628681352847439302316235957;
aggSignerApkG2.Y[1] = 354176189041917478648604979334478067325821134838555150300539079146482658331;
aggSignerApkG2.Y[0] = 4185483097059047421902184823581361466320657066600218863748375739772335928910;

// 100*aggSignerPrivKey*g2
oneHundredQuorumApkG2.X[1] = 6187649255575786743153792867265230878737103598736372524337965086852090105771;
oneHundredQuorumApkG2.X[0] = 5334877400925935887383922877430837542135722474116902175395820705628447222839;
oneHundredQuorumApkG2.Y[1] = 4668116328019846503695710811760363536142902258271850958815598072072236299223;
oneHundredQuorumApkG2.Y[0] = 21446056442597180561077194011672151329458819211586246807143487001691968661015;

sigma = BN254.hashToG1(msgHash).scalar_mul(aggSignerPrivKey);
}

function _generateSignerAndNonSignerPrivateKeys(
uint256 pseudoRandomNumber,
uint256 numSigners,
uint256 numNonSigners
) internal view returns (uint256[] memory, uint256[] memory) {
uint256[] memory signerPrivateKeys = new uint256[](numSigners);
// generate numSigners numbers that add up to aggSignerPrivKey mod BN254.FR_MODULUS
uint256 sum = 0;
for (uint256 i = 0; i < numSigners - 1; i++) {
signerPrivateKeys[i] =
uint256(keccak256(abi.encodePacked("signerPrivateKey", pseudoRandomNumber, i))) % BN254.FR_MODULUS;
sum = addmod(sum, signerPrivateKeys[i], BN254.FR_MODULUS);
}
// signer private keys need to add to aggSignerPrivKey
signerPrivateKeys[numSigners - 1] =
addmod(aggSignerPrivKey, BN254.FR_MODULUS - sum % BN254.FR_MODULUS, BN254.FR_MODULUS);

uint256[] memory nonSignerPrivateKeys = new uint256[](numNonSigners);
for (uint256 i = 0; i < numNonSigners; i++) {
nonSignerPrivateKeys[i] =
uint256(keccak256(abi.encodePacked("nonSignerPrivateKey", pseudoRandomNumber, i))) % BN254.FR_MODULUS;
}

// Sort nonSignerPrivateKeys in order of ascending pubkeyHash
// Uses insertion sort to sort array in place
for (uint256 i = 1; i < nonSignerPrivateKeys.length; i++) {
uint256 privateKey = nonSignerPrivateKeys[i];
bytes32 pubkeyHash = _toPubkeyHash(privateKey);
uint256 j = i;

// Move elements of nonSignerPrivateKeys[0..i-1] that are greater than the current key
// to one position ahead of their current position
while (j > 0 && _toPubkeyHash(nonSignerPrivateKeys[j - 1]) > pubkeyHash) {
nonSignerPrivateKeys[j] = nonSignerPrivateKeys[j - 1];
j--;
}
nonSignerPrivateKeys[j] = privateKey;
}

return (signerPrivateKeys, nonSignerPrivateKeys);
}

function _registerSignatoriesAndGetNonSignerStakeAndSignatureRandom(
uint256 pseudoRandomNumber,
uint256 numNonSigners,
uint256 quorumBitmap
) internal returns (uint32, BLSSignatureChecker.NonSignerStakesAndSignature memory) {
(uint256[] memory signerPrivateKeys, uint256[] memory nonSignerPrivateKeys) =
_generateSignerAndNonSignerPrivateKeys(
pseudoRandomNumber, maxOperatorsToRegister - numNonSigners, numNonSigners
);
bytes memory quorumNumbers = BitmapUtils.bitmapToBytesArray(quorumBitmap);

// randomly combine signer and non-signer private keys
uint256[] memory privateKeys = new uint256[](maxOperatorsToRegister);
// generate addresses and public keys
address[] memory operators = new address[](maxOperatorsToRegister);
BN254.G1Point[] memory pubkeys = new BN254.G1Point[](maxOperatorsToRegister);
BLSSignatureChecker.NonSignerStakesAndSignature memory nonSignerStakesAndSignature;
nonSignerStakesAndSignature.quorumApks = new BN254.G1Point[](quorumNumbers.length);
nonSignerStakesAndSignature.nonSignerPubkeys = new BN254.G1Point[](numNonSigners);
bytes32[] memory nonSignerOperatorIds = new bytes32[](numNonSigners);
{
uint256 signerIndex = 0;
uint256 nonSignerIndex = 0;
for (uint256 i = 0; i < maxOperatorsToRegister; i++) {
uint256 randomSeed = uint256(keccak256(abi.encodePacked("privKeyCombination", i)));
if (randomSeed % 2 == 0 && signerIndex < signerPrivateKeys.length) {
privateKeys[i] = signerPrivateKeys[signerIndex];
signerIndex++;
} else if (nonSignerIndex < nonSignerPrivateKeys.length) {
privateKeys[i] = nonSignerPrivateKeys[nonSignerIndex];
nonSignerStakesAndSignature.nonSignerPubkeys[nonSignerIndex] =
BN254.generatorG1().scalar_mul(privateKeys[i]);
nonSignerOperatorIds[nonSignerIndex] =
nonSignerStakesAndSignature.nonSignerPubkeys[nonSignerIndex].hashG1Point();
nonSignerIndex++;
} else {
privateKeys[i] = signerPrivateKeys[signerIndex];
signerIndex++;
}

operators[i] = _incrementAddress(defaultOperator, i);
pubkeys[i] = BN254.generatorG1().scalar_mul(privateKeys[i]);

// add the public key to each quorum
for (uint256 j = 0; j < nonSignerStakesAndSignature.quorumApks.length; j++) {
nonSignerStakesAndSignature.quorumApks[j] =
nonSignerStakesAndSignature.quorumApks[j].plus(pubkeys[i]);
}
}
}

// register all operators for the first quorum
for (uint256 i = 0; i < maxOperatorsToRegister; i++) {
cheats.roll(registrationBlockNumber + blocksBetweenRegistrations * i);
_registerOperatorWithCoordinator(operators[i], quorumBitmap, pubkeys[i], defaultStake);
}

uint32 referenceBlockNumber =
registrationBlockNumber + blocksBetweenRegistrations * uint32(maxOperatorsToRegister) + 1;
cheats.roll(referenceBlockNumber + 100);

OperatorStateRetriever.CheckSignaturesIndices memory checkSignaturesIndices = operatorStateRetriever
.getCheckSignaturesIndices(registryCoordinator, referenceBlockNumber, quorumNumbers, nonSignerOperatorIds);

nonSignerStakesAndSignature.nonSignerQuorumBitmapIndices = checkSignaturesIndices.nonSignerQuorumBitmapIndices;
nonSignerStakesAndSignature.apkG2 = aggSignerApkG2;
nonSignerStakesAndSignature.sigma = sigma;
nonSignerStakesAndSignature.quorumApkIndices = checkSignaturesIndices.quorumApkIndices;
nonSignerStakesAndSignature.totalStakeIndices = checkSignaturesIndices.totalStakeIndices;
nonSignerStakesAndSignature.nonSignerStakeIndices = checkSignaturesIndices.nonSignerStakeIndices;

return (referenceBlockNumber, nonSignerStakesAndSignature);
}

function _toPubkeyHash(uint256 privKey) internal view returns (bytes32) {
return BN254.generatorG1().scalar_mul(privKey).hashG1Point();
}
}
59 changes: 57 additions & 2 deletions contracts/test/MachServiceManager.t.sol
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.8.12;

import "./AVSDeployer.sol";
import "forge-std/Test.sol";

import "./BLSAVSDeployer.sol";
import "../src/error/Errors.sol";
import "../src/interfaces/IMachServiceManager.sol";

contract MachServiceManagerTest is AVSDeployer {
contract MachServiceManagerTest is BLSAVSDeployer {
event OperatorAllowed(address operator);
event OperatorDisallowed(address operator);
event AllowlistEnabled();
event AllowlistDisabled();
event AlertConfirmerChanged(address previousAddress, address newAddress);
event WhitelisterChanged(address previousAddress, address newAddress);
event QuorumThresholdPercentageChanged(uint8 thresholdPercentages);
event RollupChainIdUpdated(uint256 previousRollupChainId, uint256 newRollupChainId);
event AlertConfirmed(bytes32 indexed alertHeaderHash, bytes32 messageHash);

function setUp() public virtual {
_deployMockEigenLayerAndAVS();

msgHash = keccak256(
abi.encode(IMachServiceManager.ReducedAlertHeader({messageHash: "foo", referenceBlockNumber: 201}))
);

_setAggregatePublicKeysAndSignature();
}

function test_AddToAllowlist() public {
Expand Down Expand Up @@ -112,4 +126,45 @@ contract MachServiceManagerTest is AVSDeployer {
serviceManager.enableAllowlist();
vm.stopPrank();
}

function test_confirmAlert() public {
vm.startPrank(proxyAdminOwner);
serviceManager.disableAllowlist();
vm.stopPrank();

uint256 nonRandomNumber = 111;
uint256 numNonSigners = 1;
uint256 quorumBitmap = 1;
bytes memory quorumNumbers = BitmapUtils.bitmapToBytesArray(quorumBitmap);

(
uint32 referenceBlockNumber,
BLSSignatureChecker.NonSignerStakesAndSignature memory nonSignerStakesAndSignature
) = _registerSignatoriesAndGetNonSignerStakeAndSignatureRandom(nonRandomNumber, numNonSigners, quorumBitmap);

(
BLSSignatureChecker.QuorumStakeTotals memory quorumStakeTotals,
/* bytes32 signatoryRecordHash */
) = serviceManager.checkSignatures(msgHash, quorumNumbers, referenceBlockNumber, nonSignerStakesAndSignature);

bytes memory quorumThresholdPercentages = new bytes(1);
quorumThresholdPercentages[0] = bytes1(uint8(67));

IMachServiceManager.AlertHeader memory alertHeader = IMachServiceManager.AlertHeader({
messageHash: "foo",
quorumNumbers: quorumNumbers,
quorumThresholdPercentages: quorumThresholdPercentages,
referenceBlockNumber: referenceBlockNumber
});

vm.startPrank(proxyAdminOwner);
vm.expectEmit();
emit AlertConfirmed(msgHash, alertHeader.messageHash);
serviceManager.confirmAlert(alertHeader, nonSignerStakesAndSignature);

vm.expectRevert(AlreadyAdded.selector);
serviceManager.confirmAlert(alertHeader, nonSignerStakesAndSignature);

vm.stopPrank();
}
}