Skip to content

Commit c3cb239

Browse files
committed
feat(fast-inbox): introduce inboxRollingHash end to end, dual with inHash (A-1373)
Stacked on #24587 (A-1372). Part of the AZIP-22 Fast Inbox work. ## What Introduces the `inboxRollingHash` — a truncated-to-field sha256 rolling chain over the L1→L2 message leaves — end to end, carried as a **dual** of the legacy `inHash`. The legacy `inHash` remains authoritative; the rolling hash is computed and threaded everywhere but not yet enforced on L1, so this change is behavior-preserving pre-flip. Each link is `h' = sha256ToField(h_be32 || leaf_be32)` with the top byte of the digest zeroed, genesis value zero. ## Changes **Circuits (noir)** - Parity base computes the rolling chain over its real message leaves (`start_rolling_hash` → `end_rolling_hash`, `num_msgs`), asserting trailing padding lanes are zero. Parity root asserts chunk continuity (`children[i].start == children[i-1].end`) and sums the counts. - Block and checkpoint rollup public inputs carry a `{start, end}` rolling-hash pair, propagated exactly like `in_hash`. Checkpoint merges assert `right.start == left.end` (decision 11 anchoring). - The checkpoint header gains `inbox_rolling_hash` immediately after `in_hash`. - The root rollup public inputs expose the `{previous, end}` pair sourced from the merged checkpoint public inputs, so the epoch's consumed chain segment is passed through to proof verification. **L1 (Solidity)** - `ProposedHeaderLib` serializes the new header field (header 348 → 380 bytes). - `PublicInputArgs` gains `previousInboxRollingHash` / `endInboxRollingHash`; `EpochProofLib` places them at public-input positions 3 and 4 (header hashes, fees, constants and blob inputs shift by two). Both values are deliberately **unvalidated** until the Fast Inbox flip — for now they are pass-through only. **TypeScript** - `updateInboxRollingHash` / `accumulateInboxRollingHash` mirror the circuit chain; `getPreviousCheckpointInboxRollingHash` sources the previous checkpoint's end value (returns zero for checkpoint ≤ 1). The sequencer, validator, and prover populate the header field; the orchestrator threads per-base start hashes; the prover-node publisher fills the two new `PublicInputArgs`. - `RootRollupPublicInputs` gains the pair with matching serialization, conversion, factories and viem types. ## Constants - `CHECKPOINT_HEADER_LENGTH` 13 → 14, `BLOCK_ROLLUP_PUBLIC_INPUTS_LENGTH` 56 → 58, `CHECKPOINT_ROLLUP_PUBLIC_INPUTS_LENGTH` 149 → 151, `ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH` 111 → 113. - Circuit ABIs changed, so the base branch's committed `pinned-build.tar.gz` no longer matches the compiled circuits. It is dropped here rather than carried stale — `bootstrap.sh` recompiles from source whenever the pin is absent — and regenerated once the ABI settles. (#24587 keeps the base pin untouched, so the artifacts stay pinned on the train until this PR.) ## Testing - `yarn build` green; `forge test` green (870 passed); noir rollup-lib root suites green (176 passed). - stdlib serde, prover-node publisher, and the checkpoint-sub-tree / top-tree orchestrator suites green. - Cross-chain `l1_to_l2` e2e confirms the header field round-trips through L1 and the archiver (decoded `inboxRollingHash` = 0 for the genesis checkpoint, as expected). This suite is registered flaky (`.test_patterns.yml`); the repeated-consumption cases exhibit a pre-existing nullifier-sync timing race unrelated to this change. Replaces #24600.
1 parent 6b2d0c8 commit c3cb239

107 files changed

Lines changed: 8537 additions & 7443 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

l1-contracts/src/core/interfaces/IRollup.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ struct PublicInputArgs {
2727
bytes32 previousArchive;
2828
bytes32 endArchive;
2929
bytes32 outHash;
30+
// Inbox rolling-hash chain segment consumed across the proven epoch (AZIP-22 Fast Inbox). Deliberately UNVALIDATED
31+
// until the Fast Inbox flip, when they get checked against per-checkpoint records written at propose; for now they
32+
// are only passed through to the proof's public inputs.
33+
bytes32 previousInboxRollingHash;
34+
bytes32 endInboxRollingHash;
3035
address proverId;
3136
}
3237

l1-contracts/src/core/libraries/rollup/EpochProofLib.sol

Lines changed: 122 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ library EpochProofLib {
109109

110110
Epoch endEpoch = assertAcceptable(_args.start, _args.end);
111111

112+
// Rehash the supplied headers against storage once, here: the public-input assembly below reads the fee
113+
// recipient/value out of them and relies on this call having run.
112114
verifyHeaders(_args.start, _args.end, _args.headers);
113115

114116
// Verify attestations for the last checkpoint in the epoch
@@ -150,6 +152,11 @@ library EpochProofLib {
150152
* own public inputs used for generating the proof vs the ones assembled
151153
* by this contract when verifying it.
152154
*
155+
* @dev The fee recipient/value public inputs are sourced from the supplied headers, so this entry point rehashes
156+
* them against storage before assembling: an off-chain caller must not walk away with public inputs built from
157+
* unverified fee fields and only discover the mismatch when the on-chain proof reverts. The submit path verifies
158+
* the headers up front and assembles via computeEpochProofPublicInputs to avoid rehashing them twice.
159+
*
153160
* @param _start - The start of the epoch (inclusive)
154161
* @param _end - The end of the epoch (inclusive)
155162
* @param _args - Array of public inputs to the proof (previousArchive, endArchive, endTimestamp, outHash, proverId)
@@ -163,6 +170,107 @@ library EpochProofLib {
163170
ProposedHeader[] calldata _headers,
164171
bytes calldata _blobPublicInputs
165172
) internal view returns (bytes32[] memory) {
173+
verifyHeaders(_start, _end, _headers);
174+
return computeEpochProofPublicInputs(_start, _end, _args, _headers, _blobPublicInputs);
175+
}
176+
177+
/**
178+
* @notice Verifies committee attestations for the last checkpoint in the epoch before accepting the epoch proof
179+
*
180+
* @dev This verification ensures that the committee has properly validated the final state of the epoch
181+
* before the proof can be accepted. The function validates that:
182+
* 1. The provided attestations match the stored attestation hash for the checkpoint
183+
* 2. The attestations have valid signatures from committee members
184+
* 3. The attestations meet the required threshold (2/3+ of committee)
185+
*
186+
* For escape hatch epochs, attestation verification is skipped since there is no committee
187+
* involvement - only the designated escape hatch proposer can propose blocks.
188+
*
189+
* @dev Errors Thrown:
190+
* - Rollup__InvalidAttestations: Provided attestations don't match stored hash or fail validation
191+
*
192+
* @param _endCheckpointNumber The last checkpoint number in the epoch to verify attestations for
193+
* @param _attestations The committee attestations containing signatures and validator information
194+
*/
195+
function verifyLastCheckpointAttestationsAndOutHash(
196+
uint256 _endCheckpointNumber,
197+
CommitteeAttestations memory _attestations,
198+
bytes32 _outHash
199+
) private {
200+
// Get the stored attestation hash and payload digest for the last checkpoint
201+
CompressedTempCheckpointLog storage checkpointLog = STFLib.getStorageTempCheckpointLog(_endCheckpointNumber);
202+
203+
// Verify that the out hash matches the stored value
204+
// The stored out hash is part of the payloadDigest that was attested to.
205+
require(checkpointLog.outHash == _outHash, Errors.Rollup__InvalidOutHash(checkpointLog.outHash, _outHash));
206+
207+
// Verify that the provided attestations match the stored hash
208+
bytes32 providedAttestationsHash = keccak256(abi.encode(_attestations));
209+
require(providedAttestationsHash == checkpointLog.attestationsHash, Errors.Rollup__InvalidAttestations());
210+
211+
// Get the epoch for the last checkpoint
212+
Epoch epoch = STFLib.getEpochForCheckpoint(_endCheckpointNumber);
213+
214+
// Check if this is an escape hatch epoch - skip attestation verification if so
215+
// since escape hatch blocks are proposed without committee attestations.
216+
// Uses epoch-stable lookup so proof verification uses the escape hatch that was
217+
// active when the epoch started, not whatever is currently configured.
218+
{
219+
IEscapeHatch escapeHatch = ValidatorSelectionLib.getEscapeHatchForEpoch(epoch);
220+
if (address(escapeHatch) != address(0)) {
221+
(bool isOpen,) = escapeHatch.isHatchOpen(epoch);
222+
if (isOpen) {
223+
// Skip attestation verification for escape hatch epochs
224+
return;
225+
}
226+
}
227+
}
228+
229+
ValidatorSelectionLib.verifyAttestations(epoch, _attestations, checkpointLog.payloadDigest);
230+
}
231+
232+
/**
233+
* @notice Rehashes each provided checkpoint header and requires it to match the stored header hash
234+
*
235+
* @param _start The first checkpoint number in the epoch (inclusive)
236+
* @param _end The last checkpoint number in the epoch (inclusive)
237+
* @param _headers The proposed headers for each checkpoint in [_start, _end]
238+
*/
239+
function verifyHeaders(uint256 _start, uint256 _end, ProposedHeader[] calldata _headers) private view {
240+
uint256 numCheckpoints = _end - _start + 1;
241+
require(
242+
_headers.length == numCheckpoints, Errors.Rollup__InvalidCheckpointHeaderCount(numCheckpoints, _headers.length)
243+
);
244+
245+
for (uint256 i = 0; i < numCheckpoints; i++) {
246+
bytes32 expectedHeaderHash = STFLib.getHeaderHash(_start + i);
247+
bytes32 providedHeaderHash = ProposedHeaderLib.hash(_headers[i]);
248+
require(
249+
providedHeaderHash == expectedHeaderHash,
250+
Errors.Rollup__InvalidCheckpointHeader(expectedHeaderHash, providedHeaderHash)
251+
);
252+
}
253+
}
254+
255+
/**
256+
* @notice Assembles the root rollup public inputs, taking the supplied checkpoint headers as already verified
257+
*
258+
* @dev Callers must have rehashed `_headers` against the stored header hashes beforehand, since the fee
259+
* recipient/value public inputs are read straight out of them.
260+
*
261+
* @param _start - The start of the epoch (inclusive)
262+
* @param _end - The end of the epoch (inclusive)
263+
* @param _args - Array of public inputs to the proof (previousArchive, endArchive, endTimestamp, outHash, proverId)
264+
* @param _headers - The proposed checkpoint headers supplying the fee recipient and value for each checkpoint
265+
* @param _blobPublicInputs- The blob public inputs for the proof
266+
*/
267+
function computeEpochProofPublicInputs(
268+
uint256 _start,
269+
uint256 _end,
270+
PublicInputArgs calldata _args,
271+
ProposedHeader[] calldata _headers,
272+
bytes calldata _blobPublicInputs
273+
) private view returns (bytes32[] memory) {
166274
RollupStore storage rollupStore = STFLib.getStorage();
167275

168276
{
@@ -191,6 +299,8 @@ library EpochProofLib {
191299
// previous_archive_root: Field,
192300
// end_archive_root: Field,
193301
// out_hash: Field,
302+
// previous_inbox_rolling_hash: Field,
303+
// end_inbox_rolling_hash: Field,
194304
// checkpointHeaderHashes: [Field; Constants.MAX_CHECKPOINTS_PER_EPOCH],
195305
// fees: [FeeRecipient; Constants.MAX_CHECKPOINTS_PER_EPOCH],
196306
// chain_id: Field,
@@ -208,15 +318,21 @@ library EpochProofLib {
208318
publicInputs[1] = _args.endArchive;
209319

210320
publicInputs[2] = _args.outHash;
321+
322+
// Inbox rolling-hash chain segment consumed across the epoch (AZIP-22 Fast Inbox). Deliberately UNVALIDATED
323+
// until the Fast Inbox flip, when they get checked against per-checkpoint records written at propose; for now
324+
// they are only passed through to the proof's public inputs.
325+
publicInputs[3] = _args.previousInboxRollingHash;
326+
publicInputs[4] = _args.endInboxRollingHash;
211327
}
212328

213329
uint256 numCheckpoints = _end - _start + 1;
214330

215331
for (uint256 i = 0; i < numCheckpoints; i++) {
216-
publicInputs[3 + i] = STFLib.getHeaderHash(_start + i);
332+
publicInputs[5 + i] = STFLib.getHeaderHash(_start + i);
217333
}
218334

219-
uint256 offset = 3 + Constants.MAX_CHECKPOINTS_PER_EPOCH;
335+
uint256 offset = 5 + Constants.MAX_CHECKPOINTS_PER_EPOCH;
220336

221337
// Taking recipient/value from the checkpoint headers rather than the prover
222338
// as defense in depth. Slots past numCheckpoints stay zero.
@@ -276,84 +392,6 @@ library EpochProofLib {
276392
return publicInputs;
277393
}
278394

279-
/**
280-
* @notice Verifies committee attestations for the last checkpoint in the epoch before accepting the epoch proof
281-
*
282-
* @dev This verification ensures that the committee has properly validated the final state of the epoch
283-
* before the proof can be accepted. The function validates that:
284-
* 1. The provided attestations match the stored attestation hash for the checkpoint
285-
* 2. The attestations have valid signatures from committee members
286-
* 3. The attestations meet the required threshold (2/3+ of committee)
287-
*
288-
* For escape hatch epochs, attestation verification is skipped since there is no committee
289-
* involvement - only the designated escape hatch proposer can propose blocks.
290-
*
291-
* @dev Errors Thrown:
292-
* - Rollup__InvalidAttestations: Provided attestations don't match stored hash or fail validation
293-
*
294-
* @param _endCheckpointNumber The last checkpoint number in the epoch to verify attestations for
295-
* @param _attestations The committee attestations containing signatures and validator information
296-
*/
297-
function verifyLastCheckpointAttestationsAndOutHash(
298-
uint256 _endCheckpointNumber,
299-
CommitteeAttestations memory _attestations,
300-
bytes32 _outHash
301-
) private {
302-
// Get the stored attestation hash and payload digest for the last checkpoint
303-
CompressedTempCheckpointLog storage checkpointLog = STFLib.getStorageTempCheckpointLog(_endCheckpointNumber);
304-
305-
// Verify that the out hash matches the stored value
306-
// The stored out hash is part of the payloadDigest that was attested to.
307-
require(checkpointLog.outHash == _outHash, Errors.Rollup__InvalidOutHash(checkpointLog.outHash, _outHash));
308-
309-
// Verify that the provided attestations match the stored hash
310-
bytes32 providedAttestationsHash = keccak256(abi.encode(_attestations));
311-
require(providedAttestationsHash == checkpointLog.attestationsHash, Errors.Rollup__InvalidAttestations());
312-
313-
// Get the epoch for the last checkpoint
314-
Epoch epoch = STFLib.getEpochForCheckpoint(_endCheckpointNumber);
315-
316-
// Check if this is an escape hatch epoch - skip attestation verification if so
317-
// since escape hatch blocks are proposed without committee attestations.
318-
// Uses epoch-stable lookup so proof verification uses the escape hatch that was
319-
// active when the epoch started, not whatever is currently configured.
320-
{
321-
IEscapeHatch escapeHatch = ValidatorSelectionLib.getEscapeHatchForEpoch(epoch);
322-
if (address(escapeHatch) != address(0)) {
323-
(bool isOpen,) = escapeHatch.isHatchOpen(epoch);
324-
if (isOpen) {
325-
// Skip attestation verification for escape hatch epochs
326-
return;
327-
}
328-
}
329-
}
330-
331-
ValidatorSelectionLib.verifyAttestations(epoch, _attestations, checkpointLog.payloadDigest);
332-
}
333-
334-
/**
335-
* @notice Rehashes each provided checkpoint header and requires it to match the stored header hash
336-
*
337-
* @param _start The first checkpoint number in the epoch (inclusive)
338-
* @param _end The last checkpoint number in the epoch (inclusive)
339-
* @param _headers The proposed headers for each checkpoint in [_start, _end]
340-
*/
341-
function verifyHeaders(uint256 _start, uint256 _end, ProposedHeader[] calldata _headers) private view {
342-
uint256 numCheckpoints = _end - _start + 1;
343-
require(
344-
_headers.length == numCheckpoints, Errors.Rollup__InvalidCheckpointHeaderCount(numCheckpoints, _headers.length)
345-
);
346-
347-
for (uint256 i = 0; i < numCheckpoints; i++) {
348-
bytes32 expectedHeaderHash = STFLib.getHeaderHash(_start + i);
349-
bytes32 providedHeaderHash = ProposedHeaderLib.hash(_headers[i]);
350-
require(
351-
providedHeaderHash == expectedHeaderHash,
352-
Errors.Rollup__InvalidCheckpointHeader(expectedHeaderHash, providedHeaderHash)
353-
);
354-
}
355-
}
356-
357395
/**
358396
* @notice Validates that an epoch proof submission meets all acceptance criteria
359397
*
@@ -421,6 +459,9 @@ library EpochProofLib {
421459
* 2. Assembling the public inputs for the root rollup circuit
422460
* 3. Verifying the validity proof against the assembled public inputs using the configured verifier
423461
*
462+
* @dev Assumes the caller has already verified the supplied checkpoint headers against storage, so assembly skips
463+
* rehashing them.
464+
*
424465
* @dev Errors Thrown:
425466
* - Rollup__InvalidBlobProof: Batched blob proof verification failed
426467
* - Rollup__InvalidProof: validity proof verification failed
@@ -436,7 +477,7 @@ library EpochProofLib {
436477
BlobLib.validateBatchedBlob(_args.blobInputs);
437478

438479
bytes32[] memory publicInputs =
439-
getEpochProofPublicInputs(_args.start, _args.end, _args.args, _args.headers, _args.blobInputs);
480+
computeEpochProofPublicInputs(_args.start, _args.end, _args.args, _args.headers, _args.blobInputs);
440481

441482
require(rollupStore.config.epochProofVerifier.verify(_args.proof, publicInputs), Errors.Rollup__InvalidProof());
442483

l1-contracts/src/core/libraries/rollup/ProposedHeaderLib.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct ProposedHeader {
2222
bytes32 blockHeadersHash;
2323
bytes32 blobsHash;
2424
bytes32 inHash;
25+
bytes32 inboxRollingHash;
2526
bytes32 outHash;
2627
Slot slotNumber;
2728
Timestamp timestamp;
@@ -56,6 +57,7 @@ library ProposedHeaderLib {
5657
_header.blockHeadersHash,
5758
_header.blobsHash,
5859
_header.inHash,
60+
_header.inboxRollingHash,
5961
_header.outHash,
6062
_header.slotNumber,
6163
Timestamp.unwrap(_header.timestamp).toUint64(),

l1-contracts/test/Rollup.t.sol

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {Registry} from "@aztec/governance/Registry.sol";
1212
import {Inbox} from "@aztec/core/messagebridge/Inbox.sol";
1313
import {Outbox} from "@aztec/core/messagebridge/Outbox.sol";
1414
import {Errors} from "@aztec/core/libraries/Errors.sol";
15-
import {ProposedHeader} from "@aztec/core/libraries/rollup/ProposedHeaderLib.sol";
15+
import {ProposedHeader, ProposedHeaderLib} from "@aztec/core/libraries/rollup/ProposedHeaderLib.sol";
1616

1717
import {
1818
IRollupCore,
@@ -874,6 +874,52 @@ contract RollupTest is RollupBase {
874874
assertEq(outbox.getRootData(Epoch.wrap(0), 2), outHash2, "Root at K=2 should be outHash2");
875875
}
876876

877+
// getEpochProofPublicInputs is the view that the prover-publisher calls off-chain to validate its inputs before
878+
// submitting. Because the fee recipient/value public inputs are taken from the supplied headers, the header check
879+
// must run here too - not only on the submit path - so a mismatch is caught before publishing rather than reverting
880+
// on-chain.
881+
function testGetEpochProofPublicInputsVerifiesHeaders() public setUpFor("empty_checkpoint_1") {
882+
_proposeCheckpoint("empty_checkpoint_1", 1);
883+
884+
DecoderBase.Data memory data = load("empty_checkpoint_1").checkpoint;
885+
CheckpointLog memory checkpoint = rollup.getCheckpoint(0);
886+
887+
PublicInputArgs memory args = PublicInputArgs({
888+
previousArchive: checkpoint.archive,
889+
endArchive: data.archive,
890+
outHash: data.header.outHash,
891+
previousInboxRollingHash: 0,
892+
endInboxRollingHash: data.header.inboxRollingHash,
893+
proverId: address(0)
894+
});
895+
896+
ProposedHeader[] memory headers = new ProposedHeader[](1);
897+
headers[0] = proposedHeaders[1];
898+
899+
// With the canonical header, the getter assembles the public inputs, sourcing the fee recipient/value from the
900+
// header.
901+
bytes32[] memory publicInputs = rollup.getEpochProofPublicInputs(1, 1, args, headers, data.batchedBlobInputs);
902+
assertEq(publicInputs.length, Constants.ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH, "Unexpected public inputs length");
903+
904+
uint256 feesOffset = 5 + Constants.MAX_CHECKPOINTS_PER_EPOCH;
905+
assertEq(
906+
publicInputs[feesOffset], bytes32(uint256(uint160(headers[0].coinbase))), "Coinbase not sourced from header"
907+
);
908+
assertEq(
909+
publicInputs[feesOffset + 1], bytes32(headers[0].accumulatedFees), "Accumulated fees not sourced from header"
910+
);
911+
912+
// Tamper a fee field so the header no longer hashes to the stored value; the getter must reject it.
913+
bytes32 expectedHeaderHash = ProposedHeaderLib.hash(headers[0]);
914+
headers[0].accumulatedFees += 1;
915+
bytes32 providedHeaderHash = ProposedHeaderLib.hash(headers[0]);
916+
917+
vm.expectRevert(
918+
abi.encodeWithSelector(Errors.Rollup__InvalidCheckpointHeader.selector, expectedHeaderHash, providedHeaderHash)
919+
);
920+
rollup.getEpochProofPublicInputs(1, 1, args, headers, data.batchedBlobInputs);
921+
}
922+
877923
function _submitEpochProof(
878924
uint256 _start,
879925
uint256 _end,
@@ -895,7 +941,12 @@ contract RollupTest is RollupBase {
895941
address _prover
896942
) internal {
897943
PublicInputArgs memory args = PublicInputArgs({
898-
previousArchive: _prevArchive, endArchive: _archive, outHash: _outHash, proverId: _prover
944+
previousArchive: _prevArchive,
945+
endArchive: _archive,
946+
outHash: _outHash,
947+
previousInboxRollingHash: 0,
948+
endInboxRollingHash: 0,
949+
proverId: _prover
899950
});
900951

901952
uint256 size = _end - _start + 1;

l1-contracts/test/base/DecoderBase.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ contract DecoderBase is TestBase {
4747
bytes32 feeRecipient;
4848
GasFees gasFees;
4949
bytes32 inHash;
50+
bytes32 inboxRollingHash;
5051
bytes32 lastArchiveRoot;
5152
bytes32 outHash;
5253
uint256 slotNumber;
@@ -104,6 +105,7 @@ contract DecoderBase is TestBase {
104105
blockHeadersHash: full.checkpoint.header.blockHeadersHash,
105106
blobsHash: full.checkpoint.header.blobsHash,
106107
inHash: full.checkpoint.header.inHash,
108+
inboxRollingHash: full.checkpoint.header.inboxRollingHash,
107109
outHash: full.checkpoint.header.outHash,
108110
slotNumber: Slot.wrap(full.checkpoint.header.slotNumber),
109111
timestamp: Timestamp.wrap(full.checkpoint.header.timestamp),

l1-contracts/test/base/RollupBase.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ contract RollupBase is DecoderBase {
7878
previousArchive: parentCheckpointLog.archive,
7979
endArchive: endFull.checkpoint.archive,
8080
outHash: endFull.checkpoint.header.outHash,
81+
previousInboxRollingHash: 0,
82+
endInboxRollingHash: 0,
8183
proverId: _prover
8284
});
8385

0 commit comments

Comments
 (0)