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

Refactor BLSApkRegistry, update tests, and modify foundry config, finished addOrRemoveBlsRegisterWhitelist test #3

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SEPOLIA_RPC_URL=
ETHERSCAN_API_KEY=
PRIVATE_KEY=
ACCOUNT_ADDRESS=
12 changes: 11 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@
src = "src"
out = "out"
libs = ["lib"]
solc = "^0.8.20"

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
solc = "0.8.22"
# https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades
ffi = true
ast = true
build_info = true
extra_output = ["storageLayout"]

[rpc_endpoints]
sepolia = "${SEPOLIA_RPC_URL}"

[etherscan]
sepolia = { key = "${ETHERSCAN_API_KEY}" }
2 changes: 1 addition & 1 deletion script/deployFinalityRelayer.s.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
pragma solidity ^0.8.20;

import "forge-std/Vm.sol";
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";
Expand Down
154 changes: 76 additions & 78 deletions src/bls/BLSApkRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import "../interfaces/IBLSApkRegistry.sol";

import "./BLSApkRegistryStorage.sol";



contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, BLSApkRegistryStorage, EIP712 {
using BN254 for BN254.G1Point;

Expand All @@ -28,43 +26,43 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B

modifier onlyRelayerManager() {
require(
msg.sender == relayerManager,
"BLSApkRegistry.onlyRelayerManager: caller is not the relayer manager address"
msg.sender == relayerManager, "BLSApkRegistry.onlyRelayerManager: caller is not the relayer manager address"
);
_;
}

constructor()
EIP712("BLSApkRegistry", "v0.0.1")
{
constructor() EIP712("BLSApkRegistry", "v0.0.1") {
_disableInitializers();
}

function initialize(
address _initialOwner,
address _finalityRelayerManager,
address _relayerManager
) external initializer {
function initialize(address _initialOwner, address _finalityRelayerManager, address _relayerManager)
external
initializer
{
_transferOwnership(_initialOwner);
finalityRelayerManager = _finalityRelayerManager;
relayerManager = _relayerManager;
_initializeApk();
}

function registerOperator(
address operator
) public onlyFinalityRelayerManager {
(BN254.G1Point memory pubkey, ) = getRegisteredPubkey(operator);
/**
* @dev Registers an operator within the system.
*
* This function allows the Finality Relayer Manager to add an operator to the system.
* The operator's public key is retrieved and used to update the associated proof (APK).
*
* @param operator The address of the operator to be registered.
*/
function registerOperator(address operator) public onlyFinalityRelayerManager {
(BN254.G1Point memory pubkey,) = getRegisteredPubkey(operator);

_processApkUpdate(pubkey);

emit OperatorAdded(operator, operatorToPubkeyHash[operator]);
}

function deregisterOperator(
address operator
) public onlyFinalityRelayerManager {
(BN254.G1Point memory pubkey, ) = getRegisteredPubkey(operator);
function deregisterOperator(address operator) public onlyFinalityRelayerManager {
(BN254.G1Point memory pubkey,) = getRegisteredPubkey(operator);

_processApkUpdate(pubkey.negate());
emit OperatorRemoved(operator, operatorToPubkeyHash[operator]);
Expand All @@ -82,10 +80,7 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B

bytes32 pubkeyHash = BN254.hashG1Point(params.pubkeyG1);

require(
pubkeyHash != ZERO_PK_HASH,
"BLSApkRegistry.registerBLSPublicKey: cannot register zero pubkey"
);
require(pubkeyHash != ZERO_PK_HASH, "BLSApkRegistry.registerBLSPublicKey: cannot register zero pubkey");
require(
operatorToPubkeyHash[operator] == bytes32(0),
"BLSApkRegistry.registerBLSPublicKey: operator already registered pubkey"
Expand All @@ -96,23 +91,30 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B
"BLSApkRegistry.registerBLSPublicKey: public key already registered"
);

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;

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");
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;

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;
Expand All @@ -123,12 +125,14 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B
return pubkeyHash;
}

function checkSignatures(
bytes32 msgHash,
uint256 referenceBlockNumber,
FinalityNonSignerAndSignature memory params
) public view returns (StakeTotals memory, bytes32) {
require(referenceBlockNumber < uint32(block.number), "BLSSignatureChecker.checkSignatures: invalid reference block");
function checkSignatures(bytes32 msgHash, uint256 referenceBlockNumber, FinalityNonSignerAndSignature memory params)
public
view
returns (StakeTotals memory, bytes32)
{
require(
referenceBlockNumber < uint32(block.number), "BLSSignatureChecker.checkSignatures: invalid reference block"
);
BN254.G1Point memory signerApk = BN254.G1Point(0, 0);
bytes32[] memory nonSignersPubkeyHashes;
if (params.nonSignerPubkeys.length > 0) {
Expand All @@ -140,25 +144,21 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B
} else {
signerApk = currentApk;
}
(bool pairingSuccessful, bool signatureIsValid) = trySignatureAndApkVerification(msgHash, signerApk, params.apkG2, params.sigma);
(bool pairingSuccessful, bool signatureIsValid) =
trySignatureAndApkVerification(msgHash, signerApk, params.apkG2, params.sigma);
require(pairingSuccessful, "BLSSignatureChecker.checkSignatures: pairing precompile call failed");
require(signatureIsValid, "BLSSignatureChecker.checkSignatures: signature is invalid");

bytes32 signatoryRecordHash = keccak256(abi.encodePacked(referenceBlockNumber, nonSignersPubkeyHashes));

StakeTotals memory stakeTotals = StakeTotals({
totalBtcStaking: params.totalBtcStake,
totalMantaStaking: params.totalMantaStake
});
StakeTotals memory stakeTotals =
StakeTotals({totalBtcStaking: params.totalBtcStake, totalMantaStaking: params.totalMantaStake});

return (stakeTotals, signatoryRecordHash);
}

function addOrRemoveBlsRegisterWhitelist(address register, bool isAdd) external onlyRelayerManager {
require(
register != address(0),
"BLSApkRegistry.addOrRemoverBlsRegisterWhitelist: operator address is zero"
);
require(register != address(0), "BLSApkRegistry.addOrRemoverBlsRegisterWhitelist: operator address is zero");
blsRegisterWhitelist[register] = isAdd;
}

Expand All @@ -167,8 +167,14 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B
BN254.G1Point memory apk,
BN254.G2Point memory apkG2,
BN254.G1Point memory sigma
) public view returns(bool pairingSuccessful, bool siganatureIsValid) {
uint256 gamma = uint256(keccak256(abi.encodePacked(msgHash, apk.X, apk.Y, apkG2.X[0], apkG2.X[1], apkG2.Y[0], apkG2.Y[1], sigma.X, sigma.Y))) % BN254.FR_MODULUS;
) public view returns (bool pairingSuccessful, bool siganatureIsValid) {
uint256 gamma = uint256(
keccak256(
abi.encodePacked(
msgHash, apk.X, apk.Y, apkG2.X[0], apkG2.X[1], apkG2.Y[0], apkG2.Y[1], sigma.X, sigma.Y
)
)
) % BN254.FR_MODULUS;
(pairingSuccessful, siganatureIsValid) = BN254.safePairing(
sigma.plus(apk.scalar_mul(gamma)),
BN254.negGeneratorG2(),
Expand All @@ -194,42 +200,34 @@ contract BLSApkRegistry is Initializable, OwnableUpgradeable, IBLSApkRegistry, B
lastUpdate.apkHash = newApkHash;
} else {
lastUpdate.nextUpdateBlockNumber = uint32(block.number);
apkHistory.push(ApkUpdate({
apkHash: newApkHash,
updateBlockNumber: uint32(block.number),
nextUpdateBlockNumber: 0
}));
apkHistory.push(
ApkUpdate({apkHash: newApkHash, updateBlockNumber: uint32(block.number), nextUpdateBlockNumber: 0})
);
}
}

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"
);
require(pubkeyHash != bytes32(0), "BLSApkRegistry.getRegisteredPubkey: operator is not registered");

return (pubkey, pubkeyHash);
}

function pubkeyRegistrationMessageHash(address operator) public view returns (BN254.G1Point memory) {
return BN254.hashToG1(
_hashTypedDataV4(
keccak256(abi.encode(PUBKEY_REGISTRATION_TYPEHASH, operator))
)
);
function getPubkeyRegMessageHash(address operator) public view returns (BN254.G1Point memory) {
return BN254.hashToG1(_hashTypedDataV4(keccak256(abi.encode(PUBKEY_REGISTRATION_TYPEHASH, operator))));
}

function _initializeApk() internal {
require(apkHistory.length == 0, "BLSApkRegistry.initializeApk: apk already exists");

apkHistory.push(ApkUpdate({
apkHash: bytes24(0),
updateBlockNumber: uint32(block.number),
nextUpdateBlockNumber: 0
}));
apkHistory.push(
ApkUpdate({apkHash: bytes24(0), updateBlockNumber: uint32(block.number), nextUpdateBlockNumber: 0})
);
}

function getPubkeyHash(address operator) public view returns (bytes32) {
return operatorToPubkeyHash[operator];
}
}
9 changes: 3 additions & 6 deletions src/bls/BLSApkRegistryStorage.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";

import "../libraries/BN254.sol";

import "../interfaces/IBLSApkRegistry.sol";
import "../interfaces/IFinalityRelayerManager.sol";
import {IBLSApkRegistry} from "../interfaces/IBLSApkRegistry.sol";
import {BN254} from "../libraries/BN254.sol";
import {Initializable} from "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";

abstract contract BLSApkRegistryStorage is Initializable, IBLSApkRegistry {
// Constants
Expand Down
29 changes: 8 additions & 21 deletions src/interfaces/IBLSApkRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,11 @@ interface IBLSApkRegistry {
uint256 totalMantaStaking;
}

event NewPubkeyRegistration(
address indexed operator,
BN254.G1Point pubkeyG1,
BN254.G2Point pubkeyG2
);
event NewPubkeyRegistration(address indexed operator, BN254.G1Point pubkeyG1, BN254.G2Point pubkeyG2);

event OperatorAdded(
address operator,
bytes32 operatorId
);
event OperatorAdded(address operator, bytes32 operatorId);

event OperatorRemoved(
address operator,
bytes32 operatorId
);
event OperatorRemoved(address operator, bytes32 operatorId);

function registerOperator(address operator) external;

Expand All @@ -55,17 +45,14 @@ interface IBLSApkRegistry {
BN254.G1Point memory msgHash
) external returns (bytes32);

function checkSignatures(
bytes32 msgHash,
uint256 referenceBlockNumber,
FinalityNonSignerAndSignature memory params
) external view returns (StakeTotals memory, bytes32);

function checkSignatures(bytes32 msgHash, uint256 referenceBlockNumber, FinalityNonSignerAndSignature memory params)
external
view
returns (StakeTotals memory, bytes32);

function getRegisteredPubkey(address operator) external view returns (BN254.G1Point memory, bytes32);

function addOrRemoveBlsRegisterWhitelist(address operator, bool isAdd) external;

function pubkeyRegistrationMessageHash(address operator) external view returns (BN254.G1Point memory);

function getPubkeyRegMessageHash(address operator) external view returns (BN254.G1Point memory);
}
2 changes: 1 addition & 1 deletion src/utils/EmptyContract.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: UNLICENSED
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract EmptyContract {
Expand Down
Loading