From e756b707d323d617b7fa7f90307f207dc6875d4a Mon Sep 17 00:00:00 2001 From: Goran Rojovic Date: Mon, 23 Sep 2024 12:15:54 +0200 Subject: [PATCH 1/3] fix --- contracts/blade/BridgeStorage.sol | 41 +++++++++++++++-- contracts/blade/ValidatorSetStorage.sol | 28 +++++++----- .../interfaces/blade/IValidatorSetStorage.sol | 22 +++++++++ docs/blade/BridgeStorage.md | 45 +++++++++++++++++-- 4 files changed, 120 insertions(+), 16 deletions(-) diff --git a/contracts/blade/BridgeStorage.sol b/contracts/blade/BridgeStorage.sol index 79ea8afd..2fecf76d 100644 --- a/contracts/blade/BridgeStorage.sol +++ b/contracts/blade/BridgeStorage.sol @@ -4,14 +4,44 @@ pragma solidity ^0.8.19; import "./ValidatorSetStorage.sol"; contract BridgeStorage is ValidatorSetStorage { - mapping(uint256 => BridgeMessageBatch) public batches; + mapping(uint256 => SignedBridgeMessageBatch) public batches; + mapping(uint256 => SignedValidatorSet) public commitedValidatorSets; mapping(uint256 => uint256) public lastCommitted; mapping(uint256 => uint256) public lastCommittedInternal; /// @custom:security write-protection="onlySystemCall()" uint256 public batchCounter; + /// @custom:security write-protection="onlySystemCall()" + uint256 public validatorSetCounter; event NewBatch(uint256 id); + /** + * @notice commits new validator set + * @param newValidatorSet new validator set + * @param signature aggregated signature of validators that signed the new validator set + * @param bitmap bitmap of which validators signed the message + */ + function commitValidatorSet( + Validator[] calldata newValidatorSet, + uint256[2] calldata signature, + bytes calldata bitmap + ) external override onlySystemCall { + _commitValidatorSet(newValidatorSet, signature, bitmap); + + SignedValidatorSet storage signedValidatorSet = commitedValidatorSets[validatorSetCounter]; + signedValidatorSet.signature = signature; + signedValidatorSet.bitmap = bitmap; + + for (uint256 i = 0; i < newValidatorSet.length; ) { + signedValidatorSet.newValidatorSet[i] = newValidatorSet[i]; + unchecked { + ++i; + } + } + + validatorSetCounter++; + } + /** * @notice commits new batch * @param batch new batch @@ -26,9 +56,14 @@ contract BridgeStorage is ValidatorSetStorage { bytes memory hash = abi.encode(keccak256(abi.encode(batch))); verifySignature(bls.hashToPoint(DOMAIN_BRIDGE, hash), signature, bitmap); - batches[batchCounter++] = batch; + SignedBridgeMessageBatch storage signedBatch = batches[batchCounter]; + signedBatch.batch = batch; + signedBatch.signature = signature; + signedBatch.bitmap = bitmap; + + emit NewBatch(batchCounter); - emit NewBatch(batchCounter - 1); + batchCounter++; } /** diff --git a/contracts/blade/ValidatorSetStorage.sol b/contracts/blade/ValidatorSetStorage.sol index 8017cee1..df0b4731 100644 --- a/contracts/blade/ValidatorSetStorage.sol +++ b/contracts/blade/ValidatorSetStorage.sol @@ -38,16 +38,8 @@ contract ValidatorSetStorage is IValidatorSetStorage, Initializable, System { Validator[] calldata newValidatorSet, uint256[2] calldata signature, bytes calldata bitmap - ) external onlySystemCall { - require(newValidatorSet.length > 0, "EMPTY_VALIDATOR_SET"); - - bytes memory hash = abi.encode(keccak256(abi.encode(newValidatorSet))); - - verifySignature(bls.hashToPoint(DOMAIN_VALIDATOR_SET, hash), signature, bitmap); - - _setNewValidatorSet(newValidatorSet); - - emit NewValidatorSet(newValidatorSet); + ) external virtual onlySystemCall { + _commitValidatorSet(newValidatorSet, signature, bitmap); } /** @@ -136,4 +128,20 @@ contract ValidatorSetStorage is IValidatorSetStorage, Initializable, System { // Get the value of the bit at the given 'index' in a byte. return uint8(bitmap[byteNumber]) & (1 << bitNumber) > 0; } + + function _commitValidatorSet( + Validator[] calldata newValidatorSet, + uint256[2] calldata signature, + bytes calldata bitmap + ) internal { + require(newValidatorSet.length > 0, "EMPTY_VALIDATOR_SET"); + + bytes memory hash = abi.encode(keccak256(abi.encode(newValidatorSet))); + + verifySignature(bls.hashToPoint(DOMAIN_VALIDATOR_SET, hash), signature, bitmap); + + _setNewValidatorSet(newValidatorSet); + + emit NewValidatorSet(newValidatorSet); + } } diff --git a/contracts/interfaces/blade/IValidatorSetStorage.sol b/contracts/interfaces/blade/IValidatorSetStorage.sol index be949818..3dee27e5 100644 --- a/contracts/interfaces/blade/IValidatorSetStorage.sol +++ b/contracts/interfaces/blade/IValidatorSetStorage.sol @@ -44,6 +44,28 @@ struct BridgeMessageBatch { uint256 destinationChainId; } +/** + * @param batch batch that is signed + * @param signature aggregated signature of validators that signed the batch + * @param bitmap bitmap of which validators signed the message + */ +struct SignedBridgeMessageBatch { + BridgeMessageBatch batch; + uint256[2] signature; + bytes bitmap; +} + +/** + * @param newValidatorSet new validator set + * @param signature aggregated signature of validators that signed the new validator set + * @param bitmap bitmap of which validators signed the message + */ +struct SignedValidatorSet { + Validator[] newValidatorSet; + uint256[2] signature; + bytes bitmap; +} + interface IValidatorSetStorage { event NewValidatorSet(Validator[] newValidatorSet); diff --git a/docs/blade/BridgeStorage.md b/docs/blade/BridgeStorage.md index 904de0c8..32985fb3 100644 --- a/docs/blade/BridgeStorage.md +++ b/docs/blade/BridgeStorage.md @@ -149,7 +149,7 @@ function batchCounter() external view returns (uint256) ### batches ```solidity -function batches(uint256) external view returns (uint256 sourceChainId, uint256 destinationChainId) +function batches(uint256) external view returns (struct BridgeMessageBatch batch, bytes bitmap) ``` @@ -166,8 +166,8 @@ function batches(uint256) external view returns (uint256 sourceChainId, uint256 | Name | Type | Description | |---|---|---| -| sourceChainId | uint256 | undefined | -| destinationChainId | uint256 | undefined | +| batch | BridgeMessageBatch | undefined | +| bitmap | bytes | undefined | ### bls @@ -239,6 +239,28 @@ function commitValidatorSet(Validator[] newValidatorSet, uint256[2] signature, b | signature | uint256[2] | undefined | | bitmap | bytes | undefined | +### commitedValidatorSets + +```solidity +function commitedValidatorSets(uint256) external view returns (bytes bitmap) +``` + + + + + +#### Parameters + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +#### Returns + +| Name | Type | Description | +|---|---|---| +| bitmap | bytes | undefined | + ### currentValidatorSet ```solidity @@ -369,6 +391,23 @@ function totalVotingPower() external view returns (uint256) +#### Returns + +| Name | Type | Description | +|---|---|---| +| _0 | uint256 | undefined | + +### validatorSetCounter + +```solidity +function validatorSetCounter() external view returns (uint256) +``` + + + + + + #### Returns | Name | Type | Description | From d272ea81d0ce9ef7979c981d73011a9719abf438 Mon Sep 17 00:00:00 2001 From: Goran Rojovic Date: Mon, 23 Sep 2024 13:14:34 +0200 Subject: [PATCH 2/3] NewValidatorSetStored event --- contracts/blade/BridgeStorage.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contracts/blade/BridgeStorage.sol b/contracts/blade/BridgeStorage.sol index 2fecf76d..14f9655c 100644 --- a/contracts/blade/BridgeStorage.sol +++ b/contracts/blade/BridgeStorage.sol @@ -13,7 +13,8 @@ contract BridgeStorage is ValidatorSetStorage { /// @custom:security write-protection="onlySystemCall()" uint256 public validatorSetCounter; - event NewBatch(uint256 id); + event NewBatch(uint256 indexed id); + event NewValidatorSetStored(uint256 indexed id); /** * @notice commits new validator set @@ -39,6 +40,8 @@ contract BridgeStorage is ValidatorSetStorage { } } + emit NewValidatorSetStored(validatorSetCounter); + validatorSetCounter++; } From d5c6a9e32d929e329c727dcb8d6c2295bc589c4f Mon Sep 17 00:00:00 2001 From: Goran Rojovic Date: Mon, 23 Sep 2024 15:06:44 +0200 Subject: [PATCH 3/3] comments fix --- contracts/blade/BridgeStorage.sol | 2 ++ contracts/blade/ValidatorSetStorage.sol | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/contracts/blade/BridgeStorage.sol b/contracts/blade/BridgeStorage.sol index 14f9655c..aaae61bd 100644 --- a/contracts/blade/BridgeStorage.sol +++ b/contracts/blade/BridgeStorage.sol @@ -48,6 +48,8 @@ contract BridgeStorage is ValidatorSetStorage { /** * @notice commits new batch * @param batch new batch + * @param signature aggregated signature of validators that signed the new batch + * @param bitmap bitmap of which validators signed the message */ function commitBatch( BridgeMessageBatch calldata batch, diff --git a/contracts/blade/ValidatorSetStorage.sol b/contracts/blade/ValidatorSetStorage.sol index df0b4731..40b59bc0 100644 --- a/contracts/blade/ValidatorSetStorage.sol +++ b/contracts/blade/ValidatorSetStorage.sol @@ -129,6 +129,14 @@ contract ValidatorSetStorage is IValidatorSetStorage, Initializable, System { return uint8(bitmap[byteNumber]) & (1 << bitNumber) > 0; } + /** + * @notice Commits a new validator set by verifying its signature and setting it in the storage. + * @dev This function requires that the new validator set is non-empty and verifies its signature before updating the validator set. + * @param newValidatorSet The array of validators to be set as the new validator set + * @param signature The aggregated signature of the validators that signed the new validator set + * @param bitmap The bitmap representing which validators signed the new validator set + * Emits a `NewValidatorSet` event after successfully setting the new validator set. + */ function _commitValidatorSet( Validator[] calldata newValidatorSet, uint256[2] calldata signature,