Skip to content

Commit 28773a0

Browse files
authored
fix: OperatorTableUpdater encoding (#1456)
**Motivation:** The encoding in the `OperatorTableUpdater` was incorrect, as it expected the `OperatorTableInfo` was in decoded format, but it is first in bytes then needs to be decoded to `BN254OperatorSetInfo` or `ECDSAOperatorSetInfo[]` **Modifications:** Update the `OperatorTableUpdater` to decode the table to bytes first, then decode to `BN254OperatorSetInfo` or `ECDSAOperatorSetInfo[]` based on the `KeyType`. **Result:** Correct decoding/encoding
1 parent 99ffd68 commit 28773a0

File tree

2 files changed

+38
-25
lines changed

2 files changed

+38
-25
lines changed

src/contracts/multichain/OperatorTableUpdater.sol

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@ contract OperatorTableUpdater is Initializable, OwnableUpgradeable, OperatorTabl
9494
bytes calldata proof,
9595
bytes calldata operatorTableBytes
9696
) external {
97-
(OperatorSet memory operatorSet, CurveType curveType, OperatorSetConfig memory operatorSetConfig) =
98-
_getOperatorTableInfo(operatorTableBytes);
97+
(
98+
OperatorSet memory operatorSet,
99+
CurveType curveType,
100+
OperatorSetConfig memory operatorSetConfig,
101+
bytes memory operatorTableInfo
102+
) = _decodeOperatorTableBytes(operatorTableBytes);
99103

100104
// Check that the `referenceTimestamp` is greater than the latest reference timestamp
101105
require(
@@ -116,11 +120,11 @@ contract OperatorTableUpdater is Initializable, OwnableUpgradeable, OperatorTabl
116120
// Update the operator table
117121
if (curveType == CurveType.BN254) {
118122
bn254CertificateVerifier.updateOperatorTable(
119-
operatorSet, referenceTimestamp, _getBN254OperatorSetInfo(operatorTableBytes), operatorSetConfig
123+
operatorSet, referenceTimestamp, _getBN254OperatorInfo(operatorTableInfo), operatorSetConfig
120124
);
121125
} else if (curveType == CurveType.ECDSA) {
122126
ecdsaCertificateVerifier.updateOperatorTable(
123-
operatorSet, referenceTimestamp, _getECDSAOperatorSetInfo(operatorTableBytes), operatorSetConfig
127+
operatorSet, referenceTimestamp, _getECDSAOperatorInfo(operatorTableInfo), operatorSetConfig
124128
);
125129
} else {
126130
revert InvalidCurveType();
@@ -254,40 +258,43 @@ contract OperatorTableUpdater is Initializable, OwnableUpgradeable, OperatorTabl
254258
* @return operatorSet The operator set
255259
* @return curveType The curve type
256260
* @return operatorSetInfo The operator set info
257-
* @dev Does NOT return the operatorInfo, as that is dependent on the curve type, see `_getBN254OperatorSetInfo` and `_getECDSAOperatorSetInfo`
261+
* @return operatorTableInfo The operator table info. This is encoded as a bytes array, and its value is dependent on the curve type, see `_getBN254OperatorInfo` and `_getECDSAOperatorInfo`
258262
*/
259-
function _getOperatorTableInfo(
263+
function _decodeOperatorTableBytes(
260264
bytes calldata operatorTable
261265
)
262266
internal
263267
pure
264-
returns (OperatorSet memory operatorSet, CurveType curveType, OperatorSetConfig memory operatorSetInfo)
268+
returns (
269+
OperatorSet memory operatorSet,
270+
CurveType curveType,
271+
OperatorSetConfig memory operatorSetInfo,
272+
bytes memory operatorTableInfo
273+
)
265274
{
266-
(operatorSet, curveType, operatorSetInfo) =
267-
abi.decode(operatorTable, (OperatorSet, CurveType, OperatorSetConfig));
275+
(operatorSet, curveType, operatorSetInfo, operatorTableInfo) =
276+
abi.decode(operatorTable, (OperatorSet, CurveType, OperatorSetConfig, bytes));
268277
}
269278

270279
/**
271280
* @notice Gets the BN254 operator set info from a bytes array
272-
* @param operatorTable The bytes containing the operator table info
281+
* @param BN254OperatorSetInfoBytes The bytes containing the operator set info
273282
* @return operatorSetInfo The BN254 operator set info
274283
*/
275-
function _getBN254OperatorSetInfo(
276-
bytes calldata operatorTable
277-
) internal pure returns (BN254OperatorSetInfo memory operatorSetInfo) {
278-
(,,, operatorSetInfo) =
279-
abi.decode(operatorTable, (OperatorSet, CurveType, OperatorSetConfig, BN254OperatorSetInfo));
284+
function _getBN254OperatorInfo(
285+
bytes memory BN254OperatorSetInfoBytes
286+
) internal pure returns (BN254OperatorSetInfo memory) {
287+
return abi.decode(BN254OperatorSetInfoBytes, (BN254OperatorSetInfo));
280288
}
281289

282290
/**
283291
* @notice Gets the ECDSA operator set info from a bytes array
284-
* @param operatorTable The bytes containing the operator table info
292+
* @param ECDSAOperatorInfoBytes The bytes containing the operator table info
285293
* @return operatorSetInfo The ECDSA operator set info
286294
*/
287-
function _getECDSAOperatorSetInfo(
288-
bytes calldata operatorTable
289-
) internal pure returns (ECDSAOperatorInfo[] memory operatorSetInfo) {
290-
(,,, operatorSetInfo) =
291-
abi.decode(operatorTable, (OperatorSet, CurveType, OperatorSetConfig, ECDSAOperatorInfo[]));
295+
function _getECDSAOperatorInfo(
296+
bytes memory ECDSAOperatorInfoBytes
297+
) internal pure returns (ECDSAOperatorInfo[] memory) {
298+
return abi.decode(ECDSAOperatorInfoBytes, (ECDSAOperatorInfo[]));
292299
}
293300
}

src/test/unit/OperatorTableUpdaterUnit.t.sol

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,10 @@ contract OperatorTableUpdaterUnitTests_updateOperatorTable_BN254 is OperatorTabl
268268
function testFuzz_BN254_correctness(Randomness r) public rand(r) {
269269
// Generate random operatorSetInfo and operatorSetConfig
270270
BN254OperatorSetInfo memory operatorSetInfo = _generateRandomBN254OperatorSetInfo(r);
271+
// Encode the operatorSetInfo as bytes, as the CrossChainRegistry expects the operatorTable to be encoded as a bytes array;
272+
bytes memory operatorSetInfoBytes = abi.encode(operatorSetInfo);
271273
OperatorSetConfig memory operatorSetConfig = _generateRandomOperatorSetConfig(r);
272-
bytes memory operatorTable = abi.encode(defaultOperatorSet, CurveType.BN254, operatorSetConfig, operatorSetInfo);
274+
bytes memory operatorTable = abi.encode(defaultOperatorSet, CurveType.BN254, operatorSetConfig, operatorSetInfoBytes);
273275
bytes32 operatorSetLeafHash = keccak256(operatorTable);
274276

275277
// Include the operatorSetInfo and operatorSetConfig in the global table root & set it
@@ -314,8 +316,10 @@ contract OperatorTableUpdaterUnitTests_updateOperatorTable_ECDSA is OperatorTabl
314316
function testFuzz_ECDSA_correctness(Randomness r) public rand(r) {
315317
// Generate random operatorSetInfo and operatorSetConfig
316318
ECDSAOperatorInfo[] memory operatorInfos = _generateRandomECDSAOperatorInfos(r);
319+
// Encode the operatorInfos as bytes, as the CrossChainRegistry expects the operatorTable to be encoded as a bytes array;
320+
bytes memory operatorInfosBytes = abi.encode(operatorInfos);
317321
OperatorSetConfig memory operatorSetConfig = _generateRandomOperatorSetConfig(r);
318-
bytes memory operatorTable = abi.encode(defaultOperatorSet, CurveType.ECDSA, operatorSetConfig, operatorInfos);
322+
bytes memory operatorTable = abi.encode(defaultOperatorSet, CurveType.ECDSA, operatorSetConfig, operatorInfosBytes);
319323
bytes32 operatorSetLeafHash = keccak256(operatorTable);
320324

321325
// Include the operatorInfos and operatorSetConfig in the global table root & set it
@@ -346,16 +350,18 @@ contract OperatorTableUpdaterUnitTests_multipleCurveTypes is OperatorTableUpdate
346350
bytes memory bn254OperatorTable;
347351
{
348352
BN254OperatorSetInfo memory bn254OperatorSetInfo = _generateRandomBN254OperatorSetInfo(r);
353+
bytes memory bn254OperatorSetInfoBytes = abi.encode(bn254OperatorSetInfo);
349354
OperatorSetConfig memory bn254OperatorSetConfig = _generateRandomOperatorSetConfig(r);
350-
bn254OperatorTable = abi.encode(defaultOperatorSet, CurveType.BN254, bn254OperatorSetConfig, bn254OperatorSetInfo);
355+
bn254OperatorTable = abi.encode(defaultOperatorSet, CurveType.BN254, bn254OperatorSetConfig, bn254OperatorSetInfoBytes);
351356
}
352357

353358
// Generate random ECDSA operatorInfos and operatorSetConfig
354359
bytes memory ecdsaOperatorTable;
355360
{
356361
ECDSAOperatorInfo[] memory ecdsaOperatorInfos = _generateRandomECDSAOperatorInfos(r);
362+
bytes memory ecdsaOperatorInfosBytes = abi.encode(ecdsaOperatorInfos);
357363
OperatorSetConfig memory ecdsaOperatorSetConfig = _generateRandomOperatorSetConfig(r);
358-
ecdsaOperatorTable = abi.encode(defaultOperatorSet, CurveType.ECDSA, ecdsaOperatorSetConfig, ecdsaOperatorInfos);
364+
ecdsaOperatorTable = abi.encode(defaultOperatorSet, CurveType.ECDSA, ecdsaOperatorSetConfig, ecdsaOperatorInfosBytes);
359365
}
360366

361367
// Include the operatorInfos and operatorSetConfig in the global table root & set it

0 commit comments

Comments
 (0)