Skip to content

Commit 2073ba6

Browse files
authored
refactor: return error codes instead of reverting (#189)
<!-- Please read and fill out this form before submitting your PR. Please make sure you have reviewed our contributors guide before submitting your first PR. --> ## Overview Closes #166 ## Checklist <!-- Please complete the checklist to ensure that the PR is ready to be reviewed. IMPORTANT: PRs should be left in Draft until the below checklist is completed. --> - [ ] New and updated code has appropriate documentation - [ ] New and updated code has new and/or updated testing - [ ] Required CI checks are passing - [ ] Visual proof for any user facing features like CLI or documentation updates - [ ] Linked issues closed with keywords
1 parent a3bafa9 commit 2073ba6

File tree

2 files changed

+63
-54
lines changed

2 files changed

+63
-54
lines changed

src/lib/verifier/DAVerifier.sol

Lines changed: 53 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -43,36 +43,29 @@ struct AttestationProof {
4343
/// @dev The DAVerifier verifies that some shares, which were posted on Celestia, were committed to
4444
/// by the QGB smart contract.
4545
library DAVerifier {
46-
////////////
47-
// Errors //
48-
////////////
49-
50-
/// @notice The shares to the rows proof is invalid.
51-
/// @param i The index of the invalid proof.
52-
error InvalidSharesToRowsProof(uint256 i);
53-
54-
/// @notice The rows to the data root proof is invalid.
55-
/// @param i The index of the invalid proof.
56-
error InvalidRowsToDataRootProof(uint256 i);
57-
58-
/// @notice The row to the data root proof is invalid.
59-
error InvalidRowToDataRootProof();
60-
61-
/// @notice The data root tuple to the data root tuple roof proof is invalid.
62-
error InvalidDataRootTupleToDataRootTupleRootProof();
63-
64-
/// @notice The number of share proofs isn't equal to the number of rows roots.
65-
error UnequalShareProofsAndRowRootsNumber();
66-
67-
/// @notice The number of rows proofs isn't equal to the number of rows roots.
68-
error UnequalRowProofsAndRowRootsNumber();
69-
70-
/// @notice The verifier data length isn't equal to the number of shares in the shares proofs.
71-
error UnequalDataLengthAndNumberOfSharesProofs();
72-
73-
/// @notice The number of leaves in the binary merkle proof is not divisible by 4.
74-
/// @param i The provided proof number of leaves.
75-
error InvalidNumberOfLeavesInProof(uint256 i);
46+
/////////////////
47+
// Error codes //
48+
/////////////////
49+
50+
enum ErrorCodes {
51+
NoError,
52+
/// @notice The shares to the rows proof is invalid.
53+
InvalidSharesToRowsProof,
54+
/// @notice The rows to the data root proof is invalid.
55+
InvalidRowsToDataRootProof,
56+
/// @notice The row to the data root proof is invalid.
57+
InvalidRowToDataRootProof,
58+
/// @notice The data root tuple to the data root tuple roof proof is invalid.
59+
InvalidDataRootTupleToDataRootTupleRootProof,
60+
/// @notice The number of share proofs isn't equal to the number of rows roots.
61+
UnequalShareProofsAndRowRootsNumber,
62+
/// @notice The number of rows proofs isn't equal to the number of rows roots.
63+
UnequalRowProofsAndRowRootsNumber,
64+
/// @notice The verifier data length isn't equal to the number of shares in the shares proofs.
65+
UnequalDataLengthAndNumberOfSharesProofs,
66+
/// @notice The number of leaves in the binary merkle proof is not divisible by 4.
67+
InvalidNumberOfLeavesInProof
68+
}
7669

7770
///////////////
7871
// Functions //
@@ -83,20 +76,23 @@ library DAVerifier {
8376
/// @param _sharesProof The proof of the shares to the data root tuple root.
8477
/// @param _root The data root of the block that contains the shares.
8578
/// @return `true` if the proof is valid, `false` otherwise.
79+
/// @return an error code if the proof is invalid, ErrorCodes.NoError otherwise.
8680
function verifySharesToDataRootTupleRoot(IDAOracle _bridge, SharesProof memory _sharesProof, bytes32 _root)
8781
external
8882
view
89-
returns (bool)
83+
returns (bool, ErrorCodes)
9084
{
91-
// checking that the data root was committed to by the QGB smart contract
92-
// this will revert if the proof is not valid
93-
verifyMultiRowRootsToDataRootTupleRoot(
85+
// checking that the data root was committed to by the QGB smart contract.
86+
(bool success, ErrorCodes errorCode) = verifyMultiRowRootsToDataRootTupleRoot(
9487
_bridge, _sharesProof.rowRoots, _sharesProof.rowProofs, _sharesProof.attestationProof, _root
9588
);
89+
if (!success) {
90+
return (false, errorCode);
91+
}
9692

9793
// checking that the shares were committed to by the rows roots.
9894
if (_sharesProof.shareProofs.length != _sharesProof.rowRoots.length) {
99-
revert UnequalShareProofsAndRowRootsNumber();
95+
return (false, ErrorCodes.UnequalShareProofsAndRowRootsNumber);
10096
}
10197

10298
uint256 numberOfSharesInProofs = 0;
@@ -105,7 +101,7 @@ library DAVerifier {
105101
}
106102

107103
if (_sharesProof.data.length != numberOfSharesInProofs) {
108-
revert UnequalDataLengthAndNumberOfSharesProofs();
104+
return (false, ErrorCodes.UnequalDataLengthAndNumberOfSharesProofs);
109105
}
110106

111107
uint256 cursor = 0;
@@ -121,12 +117,12 @@ library DAVerifier {
121117
slice(_sharesProof.data, cursor, cursor + sharesUsed)
122118
)
123119
) {
124-
revert InvalidSharesToRowsProof(i);
120+
return (false, ErrorCodes.InvalidSharesToRowsProof);
125121
}
126122
cursor += sharesUsed;
127123
}
128124

129-
return true;
125+
return (true, ErrorCodes.NoError);
130126
}
131127

132128
/// @notice Verifies that a row/column root, from a Celestia block, was committed to by the QGB smart contract.
@@ -135,28 +131,29 @@ library DAVerifier {
135131
/// @param _rowProof The proof of the row/column root to the data root.
136132
/// @param _root The data root of the block that contains the row.
137133
/// @return `true` if the proof is valid, `false` otherwise.
134+
/// @return an error code if the proof is invalid, ErrorCodes.NoError otherwise.
138135
function verifyRowRootToDataRootTupleRoot(
139136
IDAOracle _bridge,
140137
NamespaceNode memory _rowRoot,
141138
BinaryMerkleProof memory _rowProof,
142139
AttestationProof memory _attestationProof,
143140
bytes32 _root
144-
) public view returns (bool) {
141+
) public view returns (bool, ErrorCodes) {
145142
// checking that the data root was committed to by the QGB smart contract
146143
if (
147144
!_bridge.verifyAttestation(
148145
_attestationProof.tupleRootNonce, _attestationProof.tuple, _attestationProof.proof
149146
)
150147
) {
151-
revert InvalidDataRootTupleToDataRootTupleRootProof();
148+
return (false, ErrorCodes.InvalidDataRootTupleToDataRootTupleRootProof);
152149
}
153150

154151
bytes memory rowRoot = abi.encodePacked(_rowRoot.min.toBytes(), _rowRoot.max.toBytes(), _rowRoot.digest);
155152
if (!BinaryMerkleTree.verify(_root, _rowProof, rowRoot)) {
156-
revert InvalidRowToDataRootProof();
153+
return (false, ErrorCodes.InvalidRowToDataRootProof);
157154
}
158155

159-
return true;
156+
return (true, ErrorCodes.NoError);
160157
}
161158

162159
/// @notice Verifies that a set of rows/columns, from a Celestia block, were committed to by the QGB smart contract.
@@ -165,36 +162,37 @@ library DAVerifier {
165162
/// @param _rowProofs The set of proofs of the _rowRoots in the same order.
166163
/// @param _root The data root of the block that contains the rows.
167164
/// @return `true` if the proof is valid, `false` otherwise.
165+
/// @return an error code if the proof is invalid, ErrorCodes.NoError otherwise.
168166
function verifyMultiRowRootsToDataRootTupleRoot(
169167
IDAOracle _bridge,
170168
NamespaceNode[] memory _rowRoots,
171169
BinaryMerkleProof[] memory _rowProofs,
172170
AttestationProof memory _attestationProof,
173171
bytes32 _root
174-
) public view returns (bool) {
172+
) public view returns (bool, ErrorCodes) {
175173
// checking that the data root was committed to by the QGB smart contract
176174
if (
177175
!_bridge.verifyAttestation(
178176
_attestationProof.tupleRootNonce, _attestationProof.tuple, _attestationProof.proof
179177
)
180178
) {
181-
revert InvalidDataRootTupleToDataRootTupleRootProof();
179+
return (false, ErrorCodes.InvalidDataRootTupleToDataRootTupleRootProof);
182180
}
183181

184182
// checking that the rows roots commit to the data root.
185183
if (_rowProofs.length != _rowRoots.length) {
186-
revert UnequalRowProofsAndRowRootsNumber();
184+
return (false, ErrorCodes.UnequalRowProofsAndRowRootsNumber);
187185
}
188186

189187
for (uint256 i = 0; i < _rowProofs.length; i++) {
190188
bytes memory rowRoot =
191189
abi.encodePacked(_rowRoots[i].min.toBytes(), _rowRoots[i].max.toBytes(), _rowRoots[i].digest);
192190
if (!BinaryMerkleTree.verify(_root, _rowProofs[i], rowRoot)) {
193-
revert InvalidRowsToDataRootProof(i);
191+
return (false, ErrorCodes.InvalidRowsToDataRootProof);
194192
}
195193
}
196194

197-
return true;
195+
return (true, ErrorCodes.NoError);
198196
}
199197

200198
/// @notice computes the Celestia block square size from a row/column root to data root binary merkle proof.
@@ -204,13 +202,18 @@ library DAVerifier {
204202
/// Note: the minimum square size is 1. Thus, we don't expect the proof to have number of leaves equal to 0.
205203
/// @param _proof The proof of the row/column root to the data root.
206204
/// @return The square size of the corresponding block.
207-
function computeSquareSizeFromRowProof(BinaryMerkleProof memory _proof) external pure returns (uint256) {
205+
/// @return an error code if the _proof is invalid, Errors.NoError otherwise.
206+
function computeSquareSizeFromRowProof(BinaryMerkleProof memory _proof)
207+
external
208+
pure
209+
returns (uint256, ErrorCodes)
210+
{
208211
if (_proof.numLeaves % 4 != 0) {
209-
revert InvalidNumberOfLeavesInProof(_proof.numLeaves);
212+
return (0, ErrorCodes.InvalidNumberOfLeavesInProof);
210213
}
211214
// we divide the number of leaves of the proof by 4 because the rows/columns tree is constructed
212215
// from the extended block row roots and column roots.
213-
return _proof.numLeaves / 4;
216+
return (_proof.numLeaves / 4, ErrorCodes.NoError);
214217
}
215218

216219
/// @notice computes the Celestia block square size from a shares to row/column root proof.

src/lib/verifier/test/DAVerifier.t.sol

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,23 +125,26 @@ contract DAVerifierTest is DSTest {
125125
SharesProof memory sharesProof =
126126
SharesProof(_data, _shareProofs, fixture.getNamespace(), _rowRoots, _rowProofs, attestationProof);
127127

128-
bool valid = DAVerifier.verifySharesToDataRootTupleRoot(bridge, sharesProof, fixture.dataRoot());
128+
(bool valid, DAVerifier.ErrorCodes errorCode) =
129+
DAVerifier.verifySharesToDataRootTupleRoot(bridge, sharesProof, fixture.dataRoot());
129130
assertTrue(valid);
131+
assertEq(uint8(errorCode), uint8(DAVerifier.ErrorCodes.NoError));
130132
}
131133

132134
function testVerifyRowRootToDataRootTupleRoot() public {
133135
AttestationProof memory attestationProof = AttestationProof(
134136
fixture.dataRootTupleRootNonce(), fixture.getDataRootTuple(), fixture.getDataRootTupleProof()
135137
);
136138

137-
bool valid = DAVerifier.verifyRowRootToDataRootTupleRoot(
139+
(bool valid, DAVerifier.ErrorCodes errorCode) = DAVerifier.verifyRowRootToDataRootTupleRoot(
138140
bridge,
139141
fixture.getFirstRowRootNode(),
140142
fixture.getRowRootToDataRootProof(),
141143
attestationProof,
142144
fixture.dataRoot()
143145
);
144146
assertTrue(valid);
147+
assertEq(uint8(errorCode), uint8(DAVerifier.ErrorCodes.NoError));
145148
}
146149

147150
function testVerifyMultiRowRootsToDataRootTupleRoot() public {
@@ -155,10 +158,11 @@ contract DAVerifierTest is DSTest {
155158
fixture.dataRootTupleRootNonce(), fixture.getDataRootTuple(), fixture.getDataRootTupleProof()
156159
);
157160

158-
bool valid = DAVerifier.verifyMultiRowRootsToDataRootTupleRoot(
161+
(bool valid, DAVerifier.ErrorCodes errorCode) = DAVerifier.verifyMultiRowRootsToDataRootTupleRoot(
159162
bridge, _rowRoots, _rowProofs, attestationProof, fixture.dataRoot()
160163
);
161164
assertTrue(valid);
165+
assertEq(uint8(errorCode), uint8(DAVerifier.ErrorCodes.NoError));
162166
}
163167

164168
function testComputeSquareSizeFromRowProof() public {
@@ -168,8 +172,10 @@ contract DAVerifierTest is DSTest {
168172

169173
// check that the computed square size is correct
170174
uint256 expectedSquareSize = 1;
171-
uint256 actualSquareSize = DAVerifier.computeSquareSizeFromRowProof(fixture.getRowRootToDataRootProof());
175+
(uint256 actualSquareSize, DAVerifier.ErrorCodes errorCode) =
176+
DAVerifier.computeSquareSizeFromRowProof(fixture.getRowRootToDataRootProof());
172177
assertEq(actualSquareSize, expectedSquareSize);
178+
assertEq(uint8(errorCode), uint8(DAVerifier.ErrorCodes.NoError));
173179
}
174180

175181
function testComputeSquareSizeFromShareProof() public {

0 commit comments

Comments
 (0)