@@ -94,32 +94,63 @@ library DAVerifier {
94
94
return (false , errorCode);
95
95
}
96
96
97
+ (bool valid , ErrorCodes error ) = verifySharesToDataRootTupleRootProof (
98
+ _sharesProof.data,
99
+ _sharesProof.shareProofs,
100
+ _sharesProof.namespace,
101
+ _sharesProof.rowRoots,
102
+ _sharesProof.rowProofs,
103
+ _root
104
+ );
105
+
106
+ return (valid, error );
107
+ }
108
+
109
+ /// @notice Verifies the shares to data root tuple root proof.
110
+ /// @param _data The data that needs to proven.
111
+ /// @param _shareProofs The share to the row roots proof.
112
+ /// @param _namespace The namespace of the shares.
113
+ /// @param _rowRoots The row roots where the shares belong.
114
+ /// @param _rowProofs The proofs of the rowRoots to the data root.
115
+ /// @param _root The data root of the block that contains the shares.
116
+ /// @return `true` if the proof is valid, `false` otherwise.
117
+ /// @return an error code if the proof is invalid, ErrorCodes.NoError otherwise.
118
+ function verifySharesToDataRootTupleRootProof (
119
+ bytes [] memory _data ,
120
+ NamespaceMerkleMultiproof[] memory _shareProofs ,
121
+ Namespace memory _namespace ,
122
+ NamespaceNode[] memory _rowRoots ,
123
+ BinaryMerkleProof[] memory _rowProofs ,
124
+ bytes32 _root
125
+ ) internal pure returns (bool , ErrorCodes) {
126
+ // verifying the row root to data root tuple root proof.
127
+ (bool success , ErrorCodes errorCode ) = verifyMultiRowRootsToDataRootTupleRootProof (_rowRoots, _rowProofs, _root);
128
+ if (! success) {
129
+ return (false , errorCode);
130
+ }
131
+
97
132
// checking that the shares were committed to by the rows roots.
98
- if (_sharesProof.shareProofs. length != _sharesProof.rowRoots .length ) {
133
+ if (_shareProofs. length != _rowRoots .length ) {
99
134
return (false , ErrorCodes.UnequalShareProofsAndRowRootsNumber);
100
135
}
101
136
102
137
uint256 numberOfSharesInProofs = 0 ;
103
- for (uint256 i = 0 ; i < _sharesProof.shareProofs .length ; i++ ) {
104
- numberOfSharesInProofs += _sharesProof.shareProofs [i].endKey - _sharesProof.shareProofs [i].beginKey;
138
+ for (uint256 i = 0 ; i < _shareProofs .length ; i++ ) {
139
+ numberOfSharesInProofs += _shareProofs [i].endKey - _shareProofs [i].beginKey;
105
140
}
106
141
107
- if (_sharesProof.data .length != numberOfSharesInProofs) {
142
+ if (_data .length != numberOfSharesInProofs) {
108
143
return (false , ErrorCodes.UnequalDataLengthAndNumberOfSharesProofs);
109
144
}
110
145
111
146
uint256 cursor = 0 ;
112
- for (uint256 i = 0 ; i < _sharesProof.shareProofs .length ; i++ ) {
113
- uint256 sharesUsed = _sharesProof.shareProofs [i].endKey - _sharesProof.shareProofs [i].beginKey;
114
- (bytes [] memory s , ErrorCodes err ) = slice (_sharesProof.data , cursor, cursor + sharesUsed);
147
+ for (uint256 i = 0 ; i < _shareProofs .length ; i++ ) {
148
+ uint256 sharesUsed = _shareProofs [i].endKey - _shareProofs [i].beginKey;
149
+ (bytes [] memory s , ErrorCodes err ) = slice (_data , cursor, cursor + sharesUsed);
115
150
if (err != ErrorCodes.NoError) {
116
151
return (false , err);
117
152
}
118
- if (
119
- ! NamespaceMerkleTree.verifyMulti (
120
- _sharesProof.rowRoots[i], _sharesProof.shareProofs[i], _sharesProof.namespace, s
121
- )
122
- ) {
153
+ if (! NamespaceMerkleTree.verifyMulti (_rowRoots[i], _shareProofs[i], _namespace, s)) {
123
154
return (false , ErrorCodes.InvalidSharesToRowsProof);
124
155
}
125
156
cursor += sharesUsed;
@@ -151,6 +182,22 @@ library DAVerifier {
151
182
return (false , ErrorCodes.InvalidDataRootTupleToDataRootTupleRootProof);
152
183
}
153
184
185
+ (bool valid , ErrorCodes error ) = verifyRowRootToDataRootTupleRootProof (_rowRoot, _rowProof, _root);
186
+
187
+ return (valid, error );
188
+ }
189
+
190
+ /// @notice Verifies that a row/column root proof, from a Celestia block, to the data root tuple root.
191
+ /// @param _rowRoot The row/column root to be proven.
192
+ /// @param _rowProof The proof of the row/column root to the data root.
193
+ /// @param _root The data root of the block that contains the row.
194
+ /// @return `true` if the proof is valid, `false` otherwise.
195
+ /// @return an error code if the proof is invalid, ErrorCodes.NoError otherwise.
196
+ function verifyRowRootToDataRootTupleRootProof (
197
+ NamespaceNode memory _rowRoot ,
198
+ BinaryMerkleProof memory _rowProof ,
199
+ bytes32 _root
200
+ ) internal pure returns (bool , ErrorCodes) {
154
201
bytes memory rowRoot = abi.encodePacked (_rowRoot.min.toBytes (), _rowRoot.max.toBytes (), _rowRoot.digest);
155
202
(bool valid ,) = BinaryMerkleTree.verify (_root, _rowProof, rowRoot);
156
203
if (! valid) {
@@ -183,6 +230,23 @@ library DAVerifier {
183
230
return (false , ErrorCodes.InvalidDataRootTupleToDataRootTupleRootProof);
184
231
}
185
232
233
+ // checking that the rows roots commit to the data root.
234
+ (bool valid , ErrorCodes error ) = verifyMultiRowRootsToDataRootTupleRootProof (_rowRoots, _rowProofs, _root);
235
+
236
+ return (valid, error );
237
+ }
238
+
239
+ /// @notice Verifies the proof a set of rows/columns, from a Celestia block, to their corresponding data root.
240
+ /// @param _rowRoots The set of row/column roots to be proved.
241
+ /// @param _rowProofs The set of proofs of the _rowRoots in the same order.
242
+ /// @param _root The data root of the block that contains the rows.
243
+ /// @return `true` if the proof is valid, `false` otherwise.
244
+ /// @return an error code if the proof is invalid, ErrorCodes.NoError otherwise.
245
+ function verifyMultiRowRootsToDataRootTupleRootProof (
246
+ NamespaceNode[] memory _rowRoots ,
247
+ BinaryMerkleProof[] memory _rowProofs ,
248
+ bytes32 _root
249
+ ) internal pure returns (bool , ErrorCodes) {
186
250
// checking that the rows roots commit to the data root.
187
251
if (_rowProofs.length != _rowRoots.length ) {
188
252
return (false , ErrorCodes.UnequalRowProofsAndRowRootsNumber);
0 commit comments