Skip to content

Commit

Permalink
test: MachServiceManager (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
neutiyoo authored May 13, 2024
1 parent c5870df commit 7ad0909
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 5 deletions.
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();
}
}

0 comments on commit 7ad0909

Please sign in to comment.