From b51e9085c8e386789bf9d128978ea6f0c1f94178 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Thu, 22 Aug 2024 14:27:05 +0000 Subject: [PATCH 01/26] feat: cleanup publisher --- l1-contracts/src/core/Rollup.sol | 156 ++++++++++++++--- l1-contracts/src/core/interfaces/IRollup.sol | 13 ++ .../src/core/libraries/DataStructures.sol | 5 + l1-contracts/src/core/libraries/Errors.sol | 1 + .../src/core/sequencer_selection/Leonidas.sol | 36 ++-- l1-contracts/test/fixtures/empty_block_1.json | 12 +- l1-contracts/test/fixtures/empty_block_2.json | 14 +- l1-contracts/test/fixtures/mixed_block_1.json | 12 +- l1-contracts/test/fixtures/mixed_block_2.json | 14 +- l1-contracts/test/sparta/DevNet.t.sol | 2 +- .../src/publisher/l1-publisher.ts | 109 ++++++++---- .../src/sequencer/sequencer.ts | 159 ++++++------------ 12 files changed, 320 insertions(+), 213 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 773c2fc6759..02a3bdda097 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -17,6 +17,8 @@ import {Errors} from "./libraries/Errors.sol"; import {Constants} from "./libraries/ConstantsGen.sol"; import {MerkleLib} from "./libraries/MerkleLib.sol"; import {SignatureLib} from "./sequencer_selection/SignatureLib.sol"; +import {SafeCast} from "@oz/utils/math/SafeCast.sol"; +import {DataStructures} from "./libraries/DataStructures.sol"; // Contracts import {MockVerifier} from "../mock/MockVerifier.sol"; @@ -31,6 +33,8 @@ import {Leonidas} from "./sequencer_selection/Leonidas.sol"; * not giving a damn about gas costs. */ contract Rollup is Leonidas, IRollup, ITestRollup { + using SafeCast for uint256; + struct BlockLog { bytes32 archive; bytes32 blockHash; @@ -381,6 +385,90 @@ contract Rollup is Leonidas, IRollup, ITestRollup { return blocks[_blockNumber].archive; } + /** + * @notice Check if a proposer can propose at a given time + * + * @param _ts - The timestamp to check + * @param _proposer - The proposer to check + * @param _archive - The archive to check (should be the latest archive) + * + * @return uint256 - The slot at the given timestamp + * @return uint256 - The block number at the given timestamp + */ + function canProposeAtTime(uint256 _ts, address _proposer, bytes32 _archive) + external + view + override(IRollup) + returns (uint256, uint256) + { + uint256 slot = getSlotAt(_ts); + + uint256 lastSlot = uint256(blocks[pendingBlockCount - 1].slotNumber); + if (slot <= lastSlot) { + revert Errors.Rollup__SlotAlreadyInChain(lastSlot, slot); + } + + bytes32 tipArchive = archive(); + if (tipArchive != _archive) { + revert Errors.Rollup__InvalidArchive(tipArchive, _archive); + } + + if (isDevNet) { + _devnetSequencerSubmissionChecks(_proposer); + } else { + address proposer = getProposerAt(_ts); + if (proposer != address(0) && proposer != _proposer) { + revert Errors.Leonidas__InvalidProposer(proposer, _proposer); + } + } + + return (slot, pendingBlockCount); + } + + /** + * @notice Validate a header for submission + * + * @dev This is a convenience function that can be used by the sequencer to validate a "partial" header + * without having to deal with viem or anvil for simulating timestamps in the future. + * + * @param _header - The header to validate + * @param _signatures - The signatures to validate + * @param _digest - The digest to validate + * @param _currentTime - The current time + * @param _flags - The flags to validate + */ + function validateHeader( + bytes calldata _header, + SignatureLib.Signature[] memory _signatures, + bytes32 _digest, + uint256 _currentTime, + DataStructures.ExecutionFlags memory _flags + ) external view override(IRollup) { + // @note This is a convenience function to allow for easier testing of the header validation + // without having to go through the entire process of submitting a block. + // This is not used in production code. + + HeaderLib.Header memory header = HeaderLib.decode(_header); + _validateHeader(header, _signatures, _digest, _currentTime, _flags); + } + + function _validateHeader( + HeaderLib.Header memory _header, + SignatureLib.Signature[] memory _signatures, + bytes32 _digest, + uint256 _currentTime, + DataStructures.ExecutionFlags memory _flags + ) internal view { + // @note This is a convenience function to allow for easier testing of the header validation + // without having to go through the entire process of submitting a block. + // This is not used in production code. + + _validateHeaderForSubmissionBase(_header, _currentTime, _flags); + _validateHeaderForSubmissionSequencerSelection( + _header.globalVariables.slotNumber, _signatures, _digest, _currentTime, _flags + ); + } + /** * @notice Processes an incoming L2 block with signatures * @@ -397,15 +485,19 @@ contract Rollup is Leonidas, IRollup, ITestRollup { ) public override(IRollup) { // Decode and validate header HeaderLib.Header memory header = HeaderLib.decode(_header); - _validateHeaderForSubmissionBase(header); - _validateHeaderForSubmissionSequencerSelection(header, _signatures, _archive); + setupEpoch(); + _validateHeader({ + _header: header, + _signatures: _signatures, + _digest: _archive, + _currentTime: block.timestamp, + _flags: DataStructures.ExecutionFlags({ignoreDA: false, ignoreSignatures: false}) + }); - // As long as the header is passing validity check in `_validateHeaderForSubmissionBase` we can safely cast - // the slot number to uint128 blocks[pendingBlockCount++] = BlockLog({ archive: _archive, blockHash: _blockHash, - slotNumber: uint128(header.globalVariables.slotNumber), + slotNumber: header.globalVariables.slotNumber.toUint128(), isProven: false }); @@ -511,15 +603,17 @@ contract Rollup is Leonidas, IRollup, ITestRollup { * * @dev While in isDevNet, we allow skipping all of the checks as we simply assume only TRUSTED sequencers * - * @param _header - The header to validate + * @param _slot - The slot of the header to validate * @param _signatures - The signatures to validate - * @param _archive - The archive root of the block + * @param _digest - The digest that signatures sign over */ function _validateHeaderForSubmissionSequencerSelection( - HeaderLib.Header memory _header, + uint256 _slot, SignatureLib.Signature[] memory _signatures, - bytes32 _archive - ) internal { + bytes32 _digest, + uint256 _currentTime, + DataStructures.ExecutionFlags memory _flags + ) internal view { if (isDevNet) { // @note If we are running in a devnet, we don't want to perform all the consensus // checks, we instead simply require that either there are NO validators or @@ -528,22 +622,15 @@ contract Rollup is Leonidas, IRollup, ITestRollup { // This means that we relaxes the condition that the block must land in the // correct slot and epoch to make it more fluid for the devnet launch // or for testing. - if (getValidatorCount() == 0) { - return; - } - if (!isValidator(msg.sender)) { - revert Errors.Leonidas__InvalidProposer(getValidatorAt(0), msg.sender); - } + _devnetSequencerSubmissionChecks(msg.sender); return; } - uint256 slot = _header.globalVariables.slotNumber; - // Ensure that the slot proposed is NOT in the future - uint256 currentSlot = getCurrentSlot(); - if (slot != currentSlot) { - revert Errors.HeaderLib__InvalidSlotNumber(currentSlot, slot); + uint256 currentSlot = getSlotAt(_currentTime); + if (_slot != currentSlot) { + revert Errors.HeaderLib__InvalidSlotNumber(currentSlot, _slot); } // @note We are currently enforcing that the slot is in the current epoch @@ -551,13 +638,13 @@ contract Rollup is Leonidas, IRollup, ITestRollup { // of an entire epoch if no-one from the new epoch committee have seen // those blocks or behaves as if they did not. - uint256 epochNumber = getEpochAt(getTimestampForSlot(slot)); - uint256 currentEpoch = getCurrentEpoch(); + uint256 epochNumber = getEpochAt(getTimestampForSlot(_slot)); + uint256 currentEpoch = getEpochAt(_currentTime); if (epochNumber != currentEpoch) { revert Errors.Rollup__InvalidEpoch(currentEpoch, epochNumber); } - _processPendingBlock(epochNumber, slot, _signatures, _archive); + _processPendingBlock(_slot, _signatures, _digest, _flags); } /** @@ -577,7 +664,11 @@ contract Rollup is Leonidas, IRollup, ITestRollup { * * @param _header - The header to validate */ - function _validateHeaderForSubmissionBase(HeaderLib.Header memory _header) internal view { + function _validateHeaderForSubmissionBase( + HeaderLib.Header memory _header, + uint256 _currentTime, + DataStructures.ExecutionFlags memory _flags + ) internal view { if (block.chainid != _header.globalVariables.chainId) { revert Errors.Rollup__InvalidChainId(block.chainid, _header.globalVariables.chainId); } @@ -613,8 +704,21 @@ contract Rollup is Leonidas, IRollup, ITestRollup { } // Check if the data is available using availability oracle (change availability oracle if you want a different DA layer) - if (!AVAILABILITY_ORACLE.isAvailable(_header.contentCommitment.txsEffectsHash)) { + if ( + !_flags.ignoreDA && !AVAILABILITY_ORACLE.isAvailable(_header.contentCommitment.txsEffectsHash) + ) { revert Errors.Rollup__UnavailableTxs(_header.contentCommitment.txsEffectsHash); } } + + function _devnetSequencerSubmissionChecks(address _proposer) internal view { + if (getValidatorCount() == 0) { + return; + } + + if (!isValidator(_proposer)) { + revert Errors.DevNet__InvalidProposer(getValidatorAt(0), _proposer); + } + return; + } } diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index a2f76ee511d..4e129e052b5 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -6,6 +6,7 @@ import {IInbox} from "../interfaces/messagebridge/IInbox.sol"; import {IOutbox} from "../interfaces/messagebridge/IOutbox.sol"; import {SignatureLib} from "../sequencer_selection/SignatureLib.sol"; +import {DataStructures} from "../libraries/DataStructures.sol"; interface ITestRollup { function setDevNet(bool _devNet) external; @@ -20,6 +21,18 @@ interface IRollup { event ProgressedState(uint256 provenBlockCount, uint256 pendingBlockCount); event PrunedPending(uint256 provenBlockCount, uint256 pendingBlockCount); + function canProposeAtTime(uint256 _ts, address _proposer, bytes32 _archive) + external + view + returns (uint256, uint256); + function validateHeader( + bytes calldata _header, + SignatureLib.Signature[] memory _signatures, + bytes32 _digest, + uint256 _currentTime, + DataStructures.ExecutionFlags memory _flags + ) external view; + function prune() external; function INBOX() external view returns (IInbox); diff --git a/l1-contracts/src/core/libraries/DataStructures.sol b/l1-contracts/src/core/libraries/DataStructures.sol index 0bdc315b6de..5462e09fa1b 100644 --- a/l1-contracts/src/core/libraries/DataStructures.sol +++ b/l1-contracts/src/core/libraries/DataStructures.sol @@ -74,4 +74,9 @@ library DataStructures { uint256 blockNumber; } // docs:end:registry_snapshot + + struct ExecutionFlags { + bool ignoreDA; + bool ignoreSignatures; + } } diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index f66a393e7bb..257d7695707 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -12,6 +12,7 @@ pragma solidity >=0.8.18; library Errors { // DEVNET related error DevNet__NoPruningAllowed(); // 0x6984c590 + error DevNet__InvalidProposer(address expected, address actual); // 0x11e6e6f7 // Inbox error Inbox__Unauthorized(); // 0xe5336a6b diff --git a/l1-contracts/src/core/sequencer_selection/Leonidas.sol b/l1-contracts/src/core/sequencer_selection/Leonidas.sol index 33826e6f563..709e6fad153 100644 --- a/l1-contracts/src/core/sequencer_selection/Leonidas.sol +++ b/l1-contracts/src/core/sequencer_selection/Leonidas.sol @@ -2,6 +2,7 @@ // Copyright 2024 Aztec Labs. pragma solidity >=0.8.18; +import {DataStructures} from "../libraries/DataStructures.sol"; import {Errors} from "../libraries/Errors.sol"; import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol"; import {Ownable} from "@oz/access/Ownable.sol"; @@ -349,29 +350,18 @@ contract Leonidas is Ownable, ILeonidas { * - If the proposer is not the real proposer AND the proposer is not open * - If the number of valid attestations is insufficient * - * @param _epochNumber - The epoch number of the block * @param _slot - The slot of the block * @param _signatures - The signatures of the committee members * @param _digest - The digest of the block */ function _processPendingBlock( - uint256 _epochNumber, uint256 _slot, SignatureLib.Signature[] memory _signatures, - bytes32 _digest - ) internal { - // @note Setup the CURRENT epoch if not already done. - // not necessarily the one we are processing! - setupEpoch(); - - Epoch storage epoch = epochs[_epochNumber]; - - // We should never enter this case because of `setupEpoch` - if (epoch.sampleSeed == 0) { - revert Errors.Leonidas__EpochNotSetup(); - } - - address proposer = getProposerAt(getTimestampForSlot(_slot)); + bytes32 _digest, + DataStructures.ExecutionFlags memory _flags + ) internal view { + uint256 ts = getTimestampForSlot(_slot); + address proposer = getProposerAt(ts); // If the proposer is open, we allow anyone to propose without needing any signatures if (proposer == address(0)) { @@ -383,7 +373,17 @@ contract Leonidas is Ownable, ILeonidas { revert Errors.Leonidas__InvalidProposer(proposer, msg.sender); } - uint256 needed = epoch.committee.length * 2 / 3 + 1; + // @note This is NOT the efficient way to do it, but it is a very convenient way for us to do it + // that allows us to reduce the number of code paths. Also when changed with optimistic for + // pleistarchus, this will be changed, so we can live with it. + + if (_flags.ignoreSignatures) { + return; + } + + address[] memory committee = getCommitteeAt(ts); + + uint256 needed = committee.length * 2 / 3 + 1; if (_signatures.length < needed) { revert Errors.Leonidas__InsufficientAttestationsProvided(needed, _signatures.length); } @@ -400,7 +400,7 @@ contract Leonidas is Ownable, ILeonidas { } // The verification will throw if invalid - signature.verify(epoch.committee[i], ethSignedDigest); + signature.verify(committee[i], ethSignedDigest); validAttestations++; } diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 20b938cbc40..4f277922e9d 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x1fc4515430abede0c269e0aaf99fe032b4368b094b2a399d112144d8e0b4b803", + "archive": "0x2ee6f8720f80fcc063c1042327b734823d51455e444f72fafc9af975f18ab9c5", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -22,10 +22,10 @@ "blockNumber": 1, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000033", "chainId": 31337, - "timestamp": 1724321038, + "timestamp": 1724858655, "version": 1, - "coinbase": "0x69d2d2c697a0ac4a874c591f6906706af27eb737", - "feeRecipient": "0x2c6280804920e2ecb139fe6185aeba95ee3687e64a14ff68a72a25ab9bb0d5eb", + "coinbase": "0xf6ed6ac83b91e8a719e552711e90249ae6fb95e0", + "feeRecipient": "0x28e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -56,8 +56,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000066c70d0e69d2d2c697a0ac4a874c591f6906706af27eb7372c6280804920e2ecb139fe6185aeba95ee3687e64a14ff68a72a25ab9bb0d5eb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00acfc19a39d0814b57d47fbf843284cd2d293382e82dfcaafc819daf89b81b5", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000066cf411ff6ed6ac83b91e8a719e552711e90249ae6fb95e028e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00bc2933646ffc5ac63d957ffb345230d5fc0bfc14359cd13f3a77b60c5d1e1a", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_2.json b/l1-contracts/test/fixtures/empty_block_2.json index 0142912e043..ecbf0057f01 100644 --- a/l1-contracts/test/fixtures/empty_block_2.json +++ b/l1-contracts/test/fixtures/empty_block_2.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x2da3733e9f6522fcc8016aff753cb69100051aae6f3612a2180959adfd3293f6", + "archive": "0x0d67087b909c777b9b4c429d421047608d3b5113d6525f024403ba72f0e8c039", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -22,10 +22,10 @@ "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000035", "chainId": 31337, - "timestamp": 1724321062, + "timestamp": 1724858679, "version": 1, - "coinbase": "0x69d2d2c697a0ac4a874c591f6906706af27eb737", - "feeRecipient": "0x2c6280804920e2ecb139fe6185aeba95ee3687e64a14ff68a72a25ab9bb0d5eb", + "coinbase": "0xf6ed6ac83b91e8a719e552711e90249ae6fb95e0", + "feeRecipient": "0x28e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x1fc4515430abede0c269e0aaf99fe032b4368b094b2a399d112144d8e0b4b803" + "root": "0x2ee6f8720f80fcc063c1042327b734823d51455e444f72fafc9af975f18ab9c5" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x1fc4515430abede0c269e0aaf99fe032b4368b094b2a399d112144d8e0b4b80300000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000066c70d2669d2d2c697a0ac4a874c591f6906706af27eb7372c6280804920e2ecb139fe6185aeba95ee3687e64a14ff68a72a25ab9bb0d5eb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00318295aad2a231c68b825b4fca99e2cbb1345c82ee6d01888289771199d1b9", + "header": "0x2ee6f8720f80fcc063c1042327b734823d51455e444f72fafc9af975f18ab9c500000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000066cf4137f6ed6ac83b91e8a719e552711e90249ae6fb95e028e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00d1b60b5c9c83f637568ce4355e0127dc27d65edd9f632ab7fb3b00c9fd2199", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index 7d6b8e45d9f..a74f4b6d39a 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,7 +58,7 @@ ] }, "block": { - "archive": "0x2e509ada109d80ef634c0eca74fecd28b17727847e3b21cf01961c73b1b58978", + "archive": "0x16ff2b46f1343feaee80c00c6b6c8e4a403a5027f1a8127caa5e7c7d67b0e96a", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0800c47667396742a5474f325e2567bff3bb99b7f0bfd2b1a689b635d8b8726cce00284120278895e8d47084ae759f390e9634881e41369a257a36fe99a2369dc800a328b4a4a6ed156325253b4ab2af7ca00e21caf7963f0fba8a88ccdc3512c300705c99df420bface231f6855799db1d0ed7d39419abc47aa8c6efe2ae7aae2009299cc308de6d23788384411e024791a5b2448e455fbdd1d1f28f3ff76631f002d6c03d81ad764de51b0f34584645191cdc2aaae2ca08fb838d142b95d62f5003032f3618b2df0fa335d5fd548d6d85e42b4e7eb5fff9eb687facbbdecb8a60016cab7ddf4d1b440d53d10284c5c82a78b2d4e27dcdb44ef434ef4c6bad6783f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0800789ff73d7787206612d96dfc2143f2344de21669a3f8cae7fe9a8918631eb00084a17f00bf8793b6851a106e9155543125e0be987ad3c8334456bdda171d0b00a400f8fd336ad84f467465964008238fd1b7f9c51c22912d706cd2b874d24e002c79bdd83c14ff50a46964f838ee207564909e28af79a57fc195810d36f9b20070083c6ef1e4dd88a064e94d2582283b203cf8a2ab1667f4370eda1b4c1fe8005373dffb5b590053d7762efcf9e11280f1486ce82e7996d94ee0f5d7c093bc009eefd90eb40e79c78bac1f71ec78bdc2f8b30041974239bdc765edffed813800ea95742e72792ca7a0f66ce9f55bc47dc09d5ea08c1b9018763102776978303f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800a68d2df6e48c8b31f4c76529e586de2cd9d0f2f2fdfbc4c523db9e3a29e9b80016c236e57bf17afe324437acd1060772e3f31d4f9e734ad758d0627c4ba2a200d659011ddde95e32886bdd8c9464da1ca144ccadd539f0992b4abb491d812a00c8025bb9006a976ebd6ad940155f15f89ca0bb7312b53841fc257e7ed689c8004165f2c46b70fb183468b38f31bba7aa9d22ce8dfb61fe721470729ce1c6b100afeb60dd983514ebbaee141b2196f3eb3c9c299f576a0097872cc85a79a43f005f6bfee53d20a474901493558419dbceb3aca40e5e18915d38031498f4d2bb008791217ee341ec5dc11f7d7a31160fb1b1f2cf767062970e9526e5751956253f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0800c064a9343bfaf1345a5ad188e96aa4c5bad0b4a5590da51a9ff8f3c98ade8d008803d57dd0923c95a01b2bfbee4df6d66dc7baee1d2cd2770575feb86d040200ea64eed9489feb7bdf29bf817a6e8772e549da7b291028852d0dd3810cee9500947e8f904d41be8a4e08b146b4e1f0cd88f55722ef987d1d485c4196ab9f71002e5d9ed5d71bc3bea6edf988c4b9ba7fceb0815180d893852ed343c64ab55c0040f7f519ec89d360d83e242b6c0ce049d2b3356b8cfbf1ff3b733ef0f8a089006f5cfe5fc4a7b87c634f9e253a7cea2052229250d0c0e913eb50b5ef3612de00b759fce0eed36bb653b67255cce111b3529c383bd7d2b758f8cb53a4451f273f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b", "decodedHeader": { @@ -72,10 +72,10 @@ "blockNumber": 1, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000043", "chainId": 31337, - "timestamp": 1724320114, + "timestamp": 1724857731, "version": 1, - "coinbase": "0xa7cd83a4518a418b4dfbec14238d07ea9e6a0e58", - "feeRecipient": "0x25ce59a5810d314c43717d1b8e0bb9fb8eb574fb4250817e4125c65496cf12f1", + "coinbase": "0x210c97d1d20ae59929bf8ac222b5508cd9c37d2a", + "feeRecipient": "0x2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -106,8 +106,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000066c70972a7cd83a4518a418b4dfbec14238d07ea9e6a0e5825ce59a5810d314c43717d1b8e0bb9fb8eb574fb4250817e4125c65496cf12f1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x0020d6fe0ac1564351eed062d6592a6255b2148ecda811aebaf64769a9a98092", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000066cf3d83210c97d1d20ae59929bf8ac222b5508cd9c37d2a2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x003558e5dac17899221e594eb6d2f2089ce984a674aa63d3815afbeb964588a7", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_2.json b/l1-contracts/test/fixtures/mixed_block_2.json index 603ca2936a6..80906bf0265 100644 --- a/l1-contracts/test/fixtures/mixed_block_2.json +++ b/l1-contracts/test/fixtures/mixed_block_2.json @@ -58,7 +58,7 @@ ] }, "block": { - "archive": "0x04b567324d50f258764769f7c4d666346e730bbb64572dfb6d3a8a5fb8fe93e3", + "archive": "0x1926af497e574a918cf90e15520a8fdf4ff569f2d39fc4e72c7d23da4abbdb0a", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08003bbb1177505f3433bb062787fcac6585d30fa1a7e0b809ca5eef1cecc56cd0002d5b86280022d106b72e4425ea49f927ca2b8138fc13b3d9feeaf36ae61fb100adab9d66b73ae23a6e9127ebe0bcd963ef4312dd66878a6be131d39a7ee01c00d48f30dbb82c96c734c8abe33f4f9f75e6d0ba4462ee07d73c5335e04a02e900f31a3a4e7333ac6043a929fca12f5347e9e8bf1d67f5993860a774f10b77bc00230e3132bfa5df23e2e018b20cd4e0c75555825ee7924da73f017a279d39cd0095e2affd6b67c6ecbf77fa1e638139498e1642abb468c58ca8ce275260ea6100362e0941035fd171fab926caf55d18b22f7de99d60ac6f454386a9cce4a1ff3f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08004a32502b5d2a0cf5d776c92ef74de61a28e7882bdadeb3b0530f472704604300808c2412e2725ecaa6a6bd77e3159349e238dc7817f906ba32afd40b3cb3cb00d7d4e3b313c4cce9bd98c317ea715847a92d795b82a6f8b8144b7c61bee64200b76f07678c289f41378029b1353a73e1afbe241612a97c23e7fc059099f49d00c72046b39a9dc902cee36db5214c72315636bd824abfabdf80b1c5e6a01fd7006e0a74fec166a12f5a62954776784f01cba3be7ab876eef2e49a2ab7a5b0f900c83ddd8f6b91086bc83485adbe8056212b4d33b91840cd3dc649f9736881460022441e76225010acce7f429dc754fb3260ae1d387937978f69c67a879ed0733f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800bb07f923e24c36227d717557d58d32b99370b81f7a70d1835becc1114f7d7700624291eff6ab801e5668bc6619a3df132f8b392b063f09dfe8a69e38224eb200bd6b195f8716ab3dc93c44037cac579d25d0e77c2782b5aa62534ee25d36bc008c99d470d2c53624a8c5bedfeffdcc5356f6da89ee0e372b3ea3fa4f8cd652009944e00a3f9a7d2e8a535d3a210c3271d5732518037704d67ef5d42a8b82c200523014cb6eabe4366c6e599ba96534fc15ecc804a13fbaaacf8717e1b0a8d20005621252c4b36c113f21ad6c13b99e5cef514bdd98ef0aae4075b5cb5a000a00d80cb2a60aae6c3d2e7d27fb1519a708a18bb5b5085f78684bdee7512856a93f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0800a38df4d53fe5da3d48c97dd0f58e7a52faade40c8f50bc0f6408a2b5b3829800a3d4b994758c6630518cce3116391874b9b3b8a1bbcb36485d2702f05af359004c06e9dd14418667d7c66384699665f9222ed08be87c67293a2f1b6b4c41aa006b77b11703f0e3d21aa68c9f6d2ae8ad94ecafdb56be0c4605a0c6723e9ddc0049a087e215b640d8360f8dd98e07c77e4d2025a0dcdcaf78bc00bd6fde09680014741a52013a10622de90b1a7854f1203af5c97121a4b3774c249fba6e0dba00c783bd01c4a4cafe83fd3b4d1ce0c555be4b6d1f772cccccf86049f9af0bbe002ff3ac4d7e2f1caf1fb30e1d20eba5be2b6a42dd54690dee988a934026491e3f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd646", "decodedHeader": { @@ -72,10 +72,10 @@ "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000055", "chainId": 31337, - "timestamp": 1724320330, + "timestamp": 1724857947, "version": 1, - "coinbase": "0xa7cd83a4518a418b4dfbec14238d07ea9e6a0e58", - "feeRecipient": "0x25ce59a5810d314c43717d1b8e0bb9fb8eb574fb4250817e4125c65496cf12f1", + "coinbase": "0x210c97d1d20ae59929bf8ac222b5508cd9c37d2a", + "feeRecipient": "0x2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -83,7 +83,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x2e509ada109d80ef634c0eca74fecd28b17727847e3b21cf01961c73b1b58978" + "root": "0x16ff2b46f1343feaee80c00c6b6c8e4a403a5027f1a8127caa5e7c7d67b0e96a" }, "stateReference": { "l1ToL2MessageTree": { @@ -106,8 +106,8 @@ } } }, - "header": "0x2e509ada109d80ef634c0eca74fecd28b17727847e3b21cf01961c73b1b58978000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000066c70a4aa7cd83a4518a418b4dfbec14238d07ea9e6a0e5825ce59a5810d314c43717d1b8e0bb9fb8eb574fb4250817e4125c65496cf12f1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x001c5bc0fe3f9edc312a5599452feb890df0d72a034179b49335c34055ba9c05", + "header": "0x16ff2b46f1343feaee80c00c6b6c8e4a403a5027f1a8127caa5e7c7d67b0e96a000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000066cf3e5b210c97d1d20ae59929bf8ac222b5508cd9c37d2a2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x004a7a3146709849c48af3458b15956b28962ea0938fd6dd655fbb81f6e27222", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/sparta/DevNet.t.sol b/l1-contracts/test/sparta/DevNet.t.sol index d37defe7ba8..4f043de9e84 100644 --- a/l1-contracts/test/sparta/DevNet.t.sol +++ b/l1-contracts/test/sparta/DevNet.t.sol @@ -166,7 +166,7 @@ contract DevNetTest is DecoderBase { // Why don't we end up here? vm.expectRevert( abi.encodeWithSelector( - Errors.Leonidas__InvalidProposer.selector, rollup.getValidatorAt(0), ree.proposer + Errors.DevNet__InvalidProposer.selector, rollup.getValidatorAt(0), ree.proposer ) ); ree.shouldRevert = true; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 020e5077b69..9ec67f80d94 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -5,12 +5,12 @@ import { AZTEC_SLOT_DURATION, ETHEREUM_SLOT_DURATION, EthAddress, + GENESIS_ARCHIVE_ROOT, type Header, - IS_DEV_NET, type Proof, } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; -import { type Fr } from '@aztec/foundation/fields'; +import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { serializeToBuffer } from '@aztec/foundation/serialize'; import { InterruptibleSleep } from '@aztec/foundation/sleep'; @@ -20,6 +20,7 @@ import { type TelemetryClient } from '@aztec/telemetry-client'; import pick from 'lodash.pick'; import { + ContractFunctionRevertedError, type GetContractReturnType, type Hex, type HttpTransport, @@ -102,6 +103,15 @@ export type MetadataForSlot = { archive: Buffer; }; +// @note If we want to simulate in the future, we have to skip the viem simulations and use `reads` instead +// This is because the viem simulations are not able to simulate the future, only the current state. +// This means that we will be simulating as if `block.timestamp` is the same for the next block +// as for the last block. +// Nevertheless, it can be quite useful for figuring out why exactly the transaction is failing +// as a middle ground right now, we will be skipping the simulation and just sending the transaction +// but only after we have done a successful run of the `validateHeader` for the timestamp in the future. +const SKIP_SIMULATION = true; + /** * Publishes L2 blocks to L1. This implementation does *not* retry a transaction in * the event of network congestion, but should work for local development. @@ -176,20 +186,46 @@ export class L1Publisher { return Promise.resolve(EthAddress.fromString(this.account.address)); } - public async willSimulationFail(slot: bigint): Promise { - // @note When simulating or estimating gas, `viem` will use the CURRENT state of the chain - // and not the state in the next block. Meaning that the timestamp will be the same as - // the previous block, which means that the slot will also be the same. - // This effectively means that if we try to simulate for the first L1 block where we - // will be proposer, we will have a failure as the slot have not yet changed. - // @todo #8110 + public async canProposeAtNextEthBlock(archive: Buffer): Promise<[bigint, bigint]> { + const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); + const [slot, blockNumber] = await this.rollupContract.read.canProposeAtTime([ + ts, + this.account.address, + `0x${archive.toString('hex')}`, + ]); + return [slot, blockNumber]; + } - if (IS_DEV_NET) { - return false; - } + public async validateBlockForSubmission( + header: Header, + digest: Buffer = new Fr(GENESIS_ARCHIVE_ROOT).toBuffer(), + attestations: Signature[] = [], + ): Promise { + const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); - const currentSlot = BigInt(await this.rollupContract.read.getCurrentSlot()); - return currentSlot != slot; + const formattedAttestations = attestations.map(attest => attest.toViemSignature()); + const flags = { ignoreDA: true, ignoreSignatures: attestations.length == 0 }; + + const args = [ + `0x${header.toBuffer().toString('hex')}`, + formattedAttestations, + `0x${digest.toString('hex')}`, + ts, + flags, + ] as const; + + try { + await this.rollupContract.read.validateHeader(args, { account: this.account }); + } catch (error: unknown) { + // Specify the type of error + if (error instanceof ContractFunctionRevertedError) { + const err = error as ContractFunctionRevertedError; + this.log.debug(`Validation failed: ${err.message}`, err.data); + } else { + this.log.debug(`Unexpected error during validation: ${error}`); + } + throw error; // Re-throw the error if needed + } } // @note Assumes that all ethereum slots have blocks @@ -247,11 +283,11 @@ export class L1Publisher { blockHash: block.hash().toString(), }; - if (await this.willSimulationFail(block.header.globalVariables.slotNumber.toBigInt())) { - // @note See comment in willSimulationFail for more information - this.log.info(`Simulation will fail for slot ${block.header.globalVariables.slotNumber.toBigInt()}`); - return false; - } + // @note This will make sure that we are passing the checks for our header ASSUMING that the data is also made available + // This means that we can avoid the simulation issues in later checks. + // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which + // make time consistency checks break. + await this.validateBlockForSubmission(block.header, block.archive.root.toBuffer(), attestations); const processTxArgs = { header: block.header.toBuffer(), @@ -436,9 +472,11 @@ export class L1Publisher { `0x${proof.toString('hex')}`, ] as const; - await this.rollupContract.simulate.submitBlockRootProof(args, { - account: this.account, - }); + if (!SKIP_SIMULATION) { + await this.rollupContract.simulate.submitBlockRootProof(args, { + account: this.account, + }); + } return await this.rollupContract.write.submitBlockRootProof(args, { account: this.account, @@ -449,6 +487,7 @@ export class L1Publisher { } } + // This is used in `integration_l1_publisher.test.ts` currently. Could be removed though. private async sendPublishTx(encodedBody: Buffer): Promise { if (!this.interrupted) { try { @@ -481,7 +520,9 @@ export class L1Publisher { attestations, ] as const; - await this.rollupContract.simulate.process(args, { account: this.account }); + if (!SKIP_SIMULATION) { + await this.rollupContract.simulate.process(args, { account: this.account }); + } return await this.rollupContract.write.process(args, { account: this.account, @@ -493,8 +534,9 @@ export class L1Publisher { `0x${encodedData.blockHash.toString('hex')}`, ] as const; - await this.rollupContract.simulate.process(args, { account: this.account }); - + if (!SKIP_SIMULATION) { + await this.rollupContract.simulate.process(args, { account: this.account }); + } return await this.rollupContract.write.process(args, { account: this.account, }); @@ -519,10 +561,11 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - // Using simulate to get a meaningful error message - await this.rollupContract.simulate.publishAndProcess(args, { - account: this.account, - }); + if (!SKIP_SIMULATION) { + await this.rollupContract.simulate.publishAndProcess(args, { + account: this.account, + }); + } return await this.rollupContract.write.publishAndProcess(args, { account: this.account, @@ -535,9 +578,11 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - await this.rollupContract.simulate.publishAndProcess(args, { - account: this.account, - }); + if (!SKIP_SIMULATION) { + await this.rollupContract.simulate.publishAndProcess(args, { + account: this.account, + }); + } return await this.rollupContract.write.publishAndProcess(args, { account: this.account, diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index aec543dfef4..122df289b8d 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -10,7 +10,16 @@ import { } from '@aztec/circuit-types'; import { type AllowedElement, BlockProofError, PROVING_STATUS } from '@aztec/circuit-types/interfaces'; import { type L2BlockBuiltStats } from '@aztec/circuit-types/stats'; -import { AztecAddress, EthAddress, type GlobalVariables, type Header, IS_DEV_NET } from '@aztec/circuits.js'; +import { + AppendOnlyTreeSnapshot, + AztecAddress, + ContentCommitment, + EthAddress, + GENESIS_ARCHIVE_ROOT, + Header, + IS_DEV_NET, + StateReference, +} from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { RunningPromise } from '@aztec/foundation/running-promise'; @@ -21,6 +30,8 @@ import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec import { type ValidatorClient } from '@aztec/validator-client'; import { type WorldStateStatus, type WorldStateSynchronizer } from '@aztec/world-state'; +import { BaseError, ContractFunctionRevertedError } from 'viem'; + import { type BlockBuilderFactory } from '../block_builder/index.js'; import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js'; import { type L1Publisher } from '../publisher/l1-publisher.js'; @@ -197,11 +208,13 @@ export class Sequencer { ? await this.l2BlockSource.getBlockNumber() : Number(historicalHeader.globalVariables.blockNumber.toBigInt())) + 1; - const chainTipArchive = chainTip?.archive.root.toBuffer(); + // If we cannot find a tip archive, assume genesis. + const chainTipArchive = + chainTip == undefined ? new Fr(GENESIS_ARCHIVE_ROOT).toBuffer() : chainTip?.archive.root.toBuffer(); let slot: bigint; try { - slot = await this.canProposeBlock(historicalHeader, undefined, chainTipArchive); + slot = await this.mayProposeBlock(chainTipArchive, BigInt(newBlockNumber)); } catch (err) { this.log.debug(`Cannot propose for block ${newBlockNumber}`); return; @@ -228,6 +241,15 @@ export class Sequencer { slot, ); + // If I created a "partial" header here that should make our job much easier. + const proposalHeader = new Header( + new AppendOnlyTreeSnapshot(Fr.fromBuffer(chainTipArchive), 1), + ContentCommitment.empty(), + StateReference.empty(), + newGlobalVariables, + Fr.ZERO, + ); + // TODO: It should be responsibility of the P2P layer to validate txs before passing them on here const allValidTxs = await this.takeValidTxs( pendingTxs, @@ -246,7 +268,7 @@ export class Sequencer { return; } - await this.buildBlockAndPublish(validTxs, newGlobalVariables, historicalHeader, chainTipArchive); + await this.buildBlockAndPublish(validTxs, proposalHeader, historicalHeader); } catch (err) { if (BlockProofError.isBlockProofError(err)) { const txHashes = err.txHashes.filter(h => !h.isZero()); @@ -267,109 +289,28 @@ export class Sequencer { return this.maxSecondsBetweenBlocks > 0 && elapsed >= this.maxSecondsBetweenBlocks; } - async canProposeBlock( - historicalHeader?: Header, - globalVariables?: GlobalVariables, - tipArchive?: Buffer, - ): Promise { - // @note In order to be able to propose a block, a few conditions must be met: - // - We must be caught up to the pending chain - // - The tip archive must match the one from the L1 - // - The block number should match the one from the L1 - // - If we have built a block, the block number must match the next pending block - // - There cannot already be a block for the slot - // - If we are NOT in devnet, then the active slot must match the slot number of the block - // - The proposer must either be free for all or specifically us. - // - // Note that the ordering of these checks are NOT optimised for performance, but to resemble the ordering - // that is used in the Rollup contract: - // - _validateHeaderForSubmissionBase - // - _validateHeaderForSubmissionSequencerSelection - // - // Also, we are logging debug messages for checks that fail to make it easier to debug, as we are usually - // catching the errors. - - const { proposer, slot, pendingBlockNumber, archive } = await this.publisher.getMetadataForSlotAtNextEthBlock(); - - if (await this.publisher.willSimulationFail(slot)) { - // @note See comment in willSimulationFail for more information - const msg = `Simulation will fail for slot ${slot}`; - this.log.debug(msg); - throw new Error(msg); - } - - // If our tip of the chain is different from the tip on L1, we should not propose a block - // @note This will change along with the data publication changes. - if (tipArchive && !archive.equals(tipArchive)) { - const msg = `Tip archive does not match the one from the L1`; - this.log.debug(msg); - throw new Error(msg); - } - - // Make sure I'm caught up to the pending chain - if ( - pendingBlockNumber > 0 && - (historicalHeader == undefined || historicalHeader.globalVariables.blockNumber.toBigInt() != pendingBlockNumber) - ) { - const msg = `Not caught up to pending block ${pendingBlockNumber}`; - this.log.debug(msg); - throw new Error(msg); - } - - // If I have constructed a block, make sure that the block number matches the next pending block number - if (globalVariables) { - if (globalVariables.blockNumber.toBigInt() !== pendingBlockNumber + 1n) { - const msg = `Block number mismatch. Expected ${ - pendingBlockNumber + 1n - } but got ${globalVariables.blockNumber.toBigInt()}`; - this.log.debug(msg); - throw new Error(msg); - } + async mayProposeBlock(tipArchive: Buffer, proposalBlockNumber: bigint): Promise { + // This checks that we can propose, and gives us the slot that we are to propose for + try { + const [slot, blockNumber] = await this.publisher.canProposeAtNextEthBlock(tipArchive); - const currentBlockNumber = await this.l2BlockSource.getBlockNumber(); - if (currentBlockNumber + 1 !== globalVariables.blockNumber.toNumber()) { - this.metrics.recordCancelledBlock(); - const msg = 'New block was emitted while building block'; + if (proposalBlockNumber !== blockNumber) { + const msg = `Block number mismatch. Expected ${proposalBlockNumber} but got ${blockNumber}`; this.log.debug(msg); throw new Error(msg); } - } - // Do not go forward if there was already a block for the slot - if (historicalHeader && historicalHeader.globalVariables.slotNumber.toBigInt() === slot) { - const msg = `Block already exists for slot ${slot}`; - this.log.debug(msg); - throw new Error(msg); - } - - // Related to _validateHeaderForSubmissionSequencerSelection - - if (IS_DEV_NET) { - // If we are in devnet, make sure that we are a validator - if ((await this.publisher.getValidatorCount()) != 0n && !(await this.publisher.amIAValidator())) { - const msg = 'Not a validator in devnet'; - this.log.debug(msg); - throw new Error(msg); - } - } else { - // If I have a constructed a block, make sure that the slot matches the current slot number - if (globalVariables) { - if (slot !== globalVariables.slotNumber.toBigInt()) { - const msg = `Slot number mismatch. Expected ${slot} but got ${globalVariables.slotNumber.toBigInt()}`; - this.log.debug(msg); - throw new Error(msg); + return slot; + } catch (err) { + if (err instanceof BaseError) { + const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); + if (revertError instanceof ContractFunctionRevertedError) { + const errorName = revertError.data?.errorName ?? ''; + this.log.debug(`canProposeAtTime failed with "${errorName}"`); } } - - // Do not go forward with new block if not free for all or my turn - if (!proposer.isZero() && !proposer.equals(await this.publisher.getSenderAddress())) { - const msg = 'Not my turn to submit block'; - this.log.debug(msg); - throw new Error(msg); - } + throw err; } - - return slot; } shouldProposeBlock(historicalHeader: Header | undefined, args: ShouldProposeArgs): boolean { @@ -440,18 +381,16 @@ export class Sequencer { return true; } - @trackSpan( - 'Sequencer.buildBlockAndPublish', - (_validTxs, newGlobalVariables, _historicalHeader, _chainTipArchive) => ({ - [Attributes.BLOCK_NUMBER]: newGlobalVariables.blockNumber.toNumber(), - }), - ) + @trackSpan('Sequencer.buildBlockAndPublish', (_validTxs, proposalHeader, _historicalHeader) => ({ + [Attributes.BLOCK_NUMBER]: proposalHeader.globalVariables.blockNumber.toNumber(), + })) private async buildBlockAndPublish( validTxs: Tx[], - newGlobalVariables: GlobalVariables, + proposalHeader: Header, historicalHeader: Header | undefined, - chainTipArchive: Buffer | undefined, ): Promise { + const newGlobalVariables = proposalHeader.globalVariables; + this.metrics.recordNewBlock(newGlobalVariables.blockNumber.toNumber(), validTxs.length); const workTimer = new Timer(); this.state = SequencerState.CREATING_BLOCK; @@ -483,7 +422,7 @@ export class Sequencer { await this.p2pClient.deleteTxs(Tx.getHashes(failedTxData)); } - await this.canProposeBlock(historicalHeader, newGlobalVariables, chainTipArchive); + await this.publisher.validateBlockForSubmission(proposalHeader); if ( !this.shouldProposeBlock(historicalHeader, { validTxsCount: validTxs.length, @@ -508,7 +447,7 @@ export class Sequencer { // Block is ready, now finalise const { block } = await blockBuilder.finaliseBlock(); - await this.canProposeBlock(historicalHeader, newGlobalVariables, chainTipArchive); + await this.publisher.validateBlockForSubmission(block.header); const workDuration = workTimer.ms(); this.log.verbose( @@ -530,7 +469,6 @@ export class Sequencer { this.isFlushing = false; const attestations = await this.collectAttestations(block); - await this.canProposeBlock(historicalHeader, newGlobalVariables, chainTipArchive); try { await this.publishL2Block(block, attestations); @@ -565,6 +503,7 @@ export class Sequencer { // ; ; // / \ // _____________/_ __ \_____________ + if (IS_DEV_NET || !this.validatorClient) { return undefined; } From da2eb7a08d4ce7920fc3b55dd56328b13aacb7eb Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 28 Aug 2024 15:35:09 +0000 Subject: [PATCH 02/26] refactor: get rid of timetraveler from l1-publisher --- l1-contracts/test/fixtures/empty_block_1.json | 12 +- l1-contracts/test/fixtures/empty_block_2.json | 14 +-- l1-contracts/test/fixtures/mixed_block_1.json | 12 +- l1-contracts/test/fixtures/mixed_block_2.json | 14 +-- yarn-project/end-to-end/package.json | 10 +- yarn-project/end-to-end/package.local.json | 2 +- .../composed/integration_l1_publisher.test.ts | 1 - yarn-project/end-to-end/src/fixtures/index.ts | 1 + .../src/fixtures/snapshot_manager.ts | 19 +++ yarn-project/end-to-end/src/fixtures/utils.ts | 9 ++ .../end-to-end/src/fixtures/watcher.ts | 64 ++++++++++ yarn-project/foundation/src/config/env_var.ts | 1 - .../sequencer-client/src/publisher/config.ts | 12 +- .../src/publisher/l1-publisher.test.ts | 33 ++++- .../src/publisher/l1-publisher.ts | 115 +++++------------- .../src/sequencer/sequencer.test.ts | 53 ++++---- .../src/sequencer/sequencer.ts | 10 +- 17 files changed, 218 insertions(+), 164 deletions(-) create mode 100644 yarn-project/end-to-end/src/fixtures/watcher.ts diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 4f277922e9d..07f8afdcbe3 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x2ee6f8720f80fcc063c1042327b734823d51455e444f72fafc9af975f18ab9c5", + "archive": "0x0f24dbb7e2a507326574582c3f44c08266eb441e926f2d68ca112f358585669f", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -22,10 +22,10 @@ "blockNumber": 1, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000033", "chainId": 31337, - "timestamp": 1724858655, + "timestamp": 1724861610, "version": 1, - "coinbase": "0xf6ed6ac83b91e8a719e552711e90249ae6fb95e0", - "feeRecipient": "0x28e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0", + "coinbase": "0x872bd7c2a38898f9fc254b86f0fd95475f7eec20", + "feeRecipient": "0x2d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -56,8 +56,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000066cf411ff6ed6ac83b91e8a719e552711e90249ae6fb95e028e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00bc2933646ffc5ac63d957ffb345230d5fc0bfc14359cd13f3a77b60c5d1e1a", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000066cf4caa872bd7c2a38898f9fc254b86f0fd95475f7eec202d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00a46e722d885c3bf479f8cf2a786adfde7a8c43740214163f7f9846914cbe6f", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_2.json b/l1-contracts/test/fixtures/empty_block_2.json index ecbf0057f01..76c3b241250 100644 --- a/l1-contracts/test/fixtures/empty_block_2.json +++ b/l1-contracts/test/fixtures/empty_block_2.json @@ -8,7 +8,7 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x0d67087b909c777b9b4c429d421047608d3b5113d6525f024403ba72f0e8c039", + "archive": "0x25126f40ad58d24006e6db629c2efb1e0868a50d5c21aa342894137b2b08bc0b", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -22,10 +22,10 @@ "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000035", "chainId": 31337, - "timestamp": 1724858679, + "timestamp": 1724861634, "version": 1, - "coinbase": "0xf6ed6ac83b91e8a719e552711e90249ae6fb95e0", - "feeRecipient": "0x28e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0", + "coinbase": "0x872bd7c2a38898f9fc254b86f0fd95475f7eec20", + "feeRecipient": "0x2d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x2ee6f8720f80fcc063c1042327b734823d51455e444f72fafc9af975f18ab9c5" + "root": "0x0f24dbb7e2a507326574582c3f44c08266eb441e926f2d68ca112f358585669f" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x2ee6f8720f80fcc063c1042327b734823d51455e444f72fafc9af975f18ab9c500000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000066cf4137f6ed6ac83b91e8a719e552711e90249ae6fb95e028e8cab987a2f3b89fcb16878a71c2076c2b73a6fb26505d8d8db8cf80bb82f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00d1b60b5c9c83f637568ce4355e0127dc27d65edd9f632ab7fb3b00c9fd2199", + "header": "0x0f24dbb7e2a507326574582c3f44c08266eb441e926f2d68ca112f358585669f00000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000066cf4cc2872bd7c2a38898f9fc254b86f0fd95475f7eec202d78818b03bcaf7034fca9d658f1212c6b2aecd6839e03cc21e2846fc061202d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00de3870b035eca1a73e8adf24b738db855a034548805b300d8dbecfd2a6e66b", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index a74f4b6d39a..b38d3363fc4 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,7 +58,7 @@ ] }, "block": { - "archive": "0x16ff2b46f1343feaee80c00c6b6c8e4a403a5027f1a8127caa5e7c7d67b0e96a", + "archive": "0x1c4782ca647f1ed559bce9f625bfae6a561ce96481c49d9b31ce4df8f46124b1", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0800c47667396742a5474f325e2567bff3bb99b7f0bfd2b1a689b635d8b8726cce00284120278895e8d47084ae759f390e9634881e41369a257a36fe99a2369dc800a328b4a4a6ed156325253b4ab2af7ca00e21caf7963f0fba8a88ccdc3512c300705c99df420bface231f6855799db1d0ed7d39419abc47aa8c6efe2ae7aae2009299cc308de6d23788384411e024791a5b2448e455fbdd1d1f28f3ff76631f002d6c03d81ad764de51b0f34584645191cdc2aaae2ca08fb838d142b95d62f5003032f3618b2df0fa335d5fd548d6d85e42b4e7eb5fff9eb687facbbdecb8a60016cab7ddf4d1b440d53d10284c5c82a78b2d4e27dcdb44ef434ef4c6bad6783f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0800789ff73d7787206612d96dfc2143f2344de21669a3f8cae7fe9a8918631eb00084a17f00bf8793b6851a106e9155543125e0be987ad3c8334456bdda171d0b00a400f8fd336ad84f467465964008238fd1b7f9c51c22912d706cd2b874d24e002c79bdd83c14ff50a46964f838ee207564909e28af79a57fc195810d36f9b20070083c6ef1e4dd88a064e94d2582283b203cf8a2ab1667f4370eda1b4c1fe8005373dffb5b590053d7762efcf9e11280f1486ce82e7996d94ee0f5d7c093bc009eefd90eb40e79c78bac1f71ec78bdc2f8b30041974239bdc765edffed813800ea95742e72792ca7a0f66ce9f55bc47dc09d5ea08c1b9018763102776978303f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800a68d2df6e48c8b31f4c76529e586de2cd9d0f2f2fdfbc4c523db9e3a29e9b80016c236e57bf17afe324437acd1060772e3f31d4f9e734ad758d0627c4ba2a200d659011ddde95e32886bdd8c9464da1ca144ccadd539f0992b4abb491d812a00c8025bb9006a976ebd6ad940155f15f89ca0bb7312b53841fc257e7ed689c8004165f2c46b70fb183468b38f31bba7aa9d22ce8dfb61fe721470729ce1c6b100afeb60dd983514ebbaee141b2196f3eb3c9c299f576a0097872cc85a79a43f005f6bfee53d20a474901493558419dbceb3aca40e5e18915d38031498f4d2bb008791217ee341ec5dc11f7d7a31160fb1b1f2cf767062970e9526e5751956253f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0800c064a9343bfaf1345a5ad188e96aa4c5bad0b4a5590da51a9ff8f3c98ade8d008803d57dd0923c95a01b2bfbee4df6d66dc7baee1d2cd2770575feb86d040200ea64eed9489feb7bdf29bf817a6e8772e549da7b291028852d0dd3810cee9500947e8f904d41be8a4e08b146b4e1f0cd88f55722ef987d1d485c4196ab9f71002e5d9ed5d71bc3bea6edf988c4b9ba7fceb0815180d893852ed343c64ab55c0040f7f519ec89d360d83e242b6c0ce049d2b3356b8cfbf1ff3b733ef0f8a089006f5cfe5fc4a7b87c634f9e253a7cea2052229250d0c0e913eb50b5ef3612de00b759fce0eed36bb653b67255cce111b3529c383bd7d2b758f8cb53a4451f273f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b", "decodedHeader": { @@ -72,10 +72,10 @@ "blockNumber": 1, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000043", "chainId": 31337, - "timestamp": 1724857731, + "timestamp": 1724860686, "version": 1, - "coinbase": "0x210c97d1d20ae59929bf8ac222b5508cd9c37d2a", - "feeRecipient": "0x2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43", + "coinbase": "0x9ca40d2eb00ca73819f826b0a788dd9891e21d13", + "feeRecipient": "0x07803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -106,8 +106,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000066cf3d83210c97d1d20ae59929bf8ac222b5508cd9c37d2a2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x003558e5dac17899221e594eb6d2f2089ce984a674aa63d3815afbeb964588a7", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000066cf490e9ca40d2eb00ca73819f826b0a788dd9891e21d1307803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x004c32b99c2c2cfac2f922454f3b7dd86ee2c8c34c98369b5b6f78a4703ae74f", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_2.json b/l1-contracts/test/fixtures/mixed_block_2.json index 80906bf0265..8b58730d955 100644 --- a/l1-contracts/test/fixtures/mixed_block_2.json +++ b/l1-contracts/test/fixtures/mixed_block_2.json @@ -58,7 +58,7 @@ ] }, "block": { - "archive": "0x1926af497e574a918cf90e15520a8fdf4ff569f2d39fc4e72c7d23da4abbdb0a", + "archive": "0x1ae32d8b8b3e677d02908a8922a6d03d2ee72021039bf6a6e0fbea570b8f7b47", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08003bbb1177505f3433bb062787fcac6585d30fa1a7e0b809ca5eef1cecc56cd0002d5b86280022d106b72e4425ea49f927ca2b8138fc13b3d9feeaf36ae61fb100adab9d66b73ae23a6e9127ebe0bcd963ef4312dd66878a6be131d39a7ee01c00d48f30dbb82c96c734c8abe33f4f9f75e6d0ba4462ee07d73c5335e04a02e900f31a3a4e7333ac6043a929fca12f5347e9e8bf1d67f5993860a774f10b77bc00230e3132bfa5df23e2e018b20cd4e0c75555825ee7924da73f017a279d39cd0095e2affd6b67c6ecbf77fa1e638139498e1642abb468c58ca8ce275260ea6100362e0941035fd171fab926caf55d18b22f7de99d60ac6f454386a9cce4a1ff3f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08004a32502b5d2a0cf5d776c92ef74de61a28e7882bdadeb3b0530f472704604300808c2412e2725ecaa6a6bd77e3159349e238dc7817f906ba32afd40b3cb3cb00d7d4e3b313c4cce9bd98c317ea715847a92d795b82a6f8b8144b7c61bee64200b76f07678c289f41378029b1353a73e1afbe241612a97c23e7fc059099f49d00c72046b39a9dc902cee36db5214c72315636bd824abfabdf80b1c5e6a01fd7006e0a74fec166a12f5a62954776784f01cba3be7ab876eef2e49a2ab7a5b0f900c83ddd8f6b91086bc83485adbe8056212b4d33b91840cd3dc649f9736881460022441e76225010acce7f429dc754fb3260ae1d387937978f69c67a879ed0733f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800bb07f923e24c36227d717557d58d32b99370b81f7a70d1835becc1114f7d7700624291eff6ab801e5668bc6619a3df132f8b392b063f09dfe8a69e38224eb200bd6b195f8716ab3dc93c44037cac579d25d0e77c2782b5aa62534ee25d36bc008c99d470d2c53624a8c5bedfeffdcc5356f6da89ee0e372b3ea3fa4f8cd652009944e00a3f9a7d2e8a535d3a210c3271d5732518037704d67ef5d42a8b82c200523014cb6eabe4366c6e599ba96534fc15ecc804a13fbaaacf8717e1b0a8d20005621252c4b36c113f21ad6c13b99e5cef514bdd98ef0aae4075b5cb5a000a00d80cb2a60aae6c3d2e7d27fb1519a708a18bb5b5085f78684bdee7512856a93f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0800a38df4d53fe5da3d48c97dd0f58e7a52faade40c8f50bc0f6408a2b5b3829800a3d4b994758c6630518cce3116391874b9b3b8a1bbcb36485d2702f05af359004c06e9dd14418667d7c66384699665f9222ed08be87c67293a2f1b6b4c41aa006b77b11703f0e3d21aa68c9f6d2ae8ad94ecafdb56be0c4605a0c6723e9ddc0049a087e215b640d8360f8dd98e07c77e4d2025a0dcdcaf78bc00bd6fde09680014741a52013a10622de90b1a7854f1203af5c97121a4b3774c249fba6e0dba00c783bd01c4a4cafe83fd3b4d1ce0c555be4b6d1f772cccccf86049f9af0bbe002ff3ac4d7e2f1caf1fb30e1d20eba5be2b6a42dd54690dee988a934026491e3f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd646", "decodedHeader": { @@ -72,10 +72,10 @@ "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000055", "chainId": 31337, - "timestamp": 1724857947, + "timestamp": 1724860902, "version": 1, - "coinbase": "0x210c97d1d20ae59929bf8ac222b5508cd9c37d2a", - "feeRecipient": "0x2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43", + "coinbase": "0x9ca40d2eb00ca73819f826b0a788dd9891e21d13", + "feeRecipient": "0x07803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -83,7 +83,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x16ff2b46f1343feaee80c00c6b6c8e4a403a5027f1a8127caa5e7c7d67b0e96a" + "root": "0x1c4782ca647f1ed559bce9f625bfae6a561ce96481c49d9b31ce4df8f46124b1" }, "stateReference": { "l1ToL2MessageTree": { @@ -106,8 +106,8 @@ } } }, - "header": "0x16ff2b46f1343feaee80c00c6b6c8e4a403a5027f1a8127caa5e7c7d67b0e96a000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000066cf3e5b210c97d1d20ae59929bf8ac222b5508cd9c37d2a2f25da389d6b307aa2ba1bab55c9a7eb540ba04f28dcdeefa749277eb8c17d43000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x004a7a3146709849c48af3458b15956b28962ea0938fd6dd655fbb81f6e27222", + "header": "0x1c4782ca647f1ed559bce9f625bfae6a561ce96481c49d9b31ce4df8f46124b1000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000066cf49e69ca40d2eb00ca73819f826b0a788dd9891e21d1307803e414075315a9195dd8f9ef9154cc40db0c0a4cb08aa98e253635741c0f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00450d818debc92707ef43bd43269cfe23681e8eb7485ce97cac5fe88c08bb91", "numTxs": 4 } } \ No newline at end of file diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index e1bdd04b338..98d1e156cd4 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -15,12 +15,12 @@ "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src \"!src/web/main.js\" && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", - "test": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", - "test:profile": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 0x --output-dir \"flame_graph/{pid}.0x\" -- node --experimental-vm-modules ../node_modules/jest/bin/jest.js --runInBand --testTimeout=300000 --forceExit", + "test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test:profile": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 0x --output-dir \"flame_graph/{pid}.0x\" -- node --experimental-vm-modules ../node_modules/jest/bin/jest.js --runInBand --testTimeout=300000 --forceExit", "serve:flames": "python3 -m http.server --directory \"flame_graph\" 8000", - "test:debug": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --inspect --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", - "test:integration": "TIME_TRAVELER=${TIME_TRAVELER:-true} concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", - "test:integration:run": "TIME_TRAVELER=${TIME_TRAVELER:-true} NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --no-cache --runInBand --config jest.integration.config.json", + "test:debug": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --inspect --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", + "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --no-cache --runInBand --config jest.integration.config.json", "test:unit": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest src/fixtures" }, "dependencies": { diff --git a/yarn-project/end-to-end/package.local.json b/yarn-project/end-to-end/package.local.json index c76111c3c26..62f136fa45d 100644 --- a/yarn-project/end-to-end/package.local.json +++ b/yarn-project/end-to-end/package.local.json @@ -2,7 +2,7 @@ "scripts": { "build": "yarn clean && tsc -b && webpack", "formatting": "run -T prettier --check ./src \"!src/web/main.js\" && run -T eslint ./src", - "test": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", "test:unit": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest src/fixtures" } } \ No newline at end of file diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 563f6cdd84d..661a4e36dc6 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -170,7 +170,6 @@ describe('L1Publisher integration', () => { publisherPrivateKey: sequencerPK, l1PublishRetryIntervalMS: 100, l1ChainId: 31337, - timeTraveler: true, }, new NoopTelemetryClient(), ); diff --git a/yarn-project/end-to-end/src/fixtures/index.ts b/yarn-project/end-to-end/src/fixtures/index.ts index 146faa68d45..270da9ae54c 100644 --- a/yarn-project/end-to-end/src/fixtures/index.ts +++ b/yarn-project/end-to-end/src/fixtures/index.ts @@ -1,3 +1,4 @@ export * from './fixtures.js'; export * from './logging.js'; export * from './utils.js'; +export * from './watcher.js'; diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index a00fe468316..6b821026179 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -41,6 +41,7 @@ import { getACVMConfig } from './get_acvm_config.js'; import { getBBConfig } from './get_bb_config.js'; import { setupL1Contracts } from './setup_l1_contracts.js'; import { deployCanonicalAuthRegistry, deployCanonicalKeyRegistry, getPrivateKeyFromIndex } from './utils.js'; +import { Watcher } from './watcher.js'; export type SubsystemsContext = { anvil: Anvil; @@ -51,6 +52,7 @@ export type SubsystemsContext = { pxe: PXEService; deployL1ContractsValues: DeployL1Contracts; proverNode: ProverNode; + watcher: Watcher; }; type SnapshotEntry = { @@ -229,6 +231,7 @@ async function teardown(context: SubsystemsContext | undefined) { await context.pxe.stop(); await context.acvmConfig?.cleanup(); await context.anvil.stop(); + await context.watcher.stop(); } export async function createAndSyncProverNode( @@ -338,6 +341,13 @@ async function setupFromFresh( aztecNode, ); + const watcher = new Watcher( + new EthCheatCodes(aztecNodeConfig.l1RpcUrl), + deployL1ContractsValues.l1ContractAddresses.rollupAddress, + deployL1ContractsValues.publicClient, + ); + watcher.start(); + logger.verbose('Creating pxe...'); const pxeConfig = getPXEServiceConfig(); pxeConfig.dataDirectory = statePath; @@ -365,6 +375,7 @@ async function setupFromFresh( bbConfig, deployL1ContractsValues, proverNode, + watcher, }; } @@ -408,6 +419,13 @@ async function setupFromState(statePath: string, logger: Logger): Promise 0 ? await createAccounts(pxe, numberOfAccounts) : []; const cheatCodes = CheatCodes.create(config.l1RpcUrl, pxe!); @@ -469,6 +477,7 @@ export async function setup( } await anvil?.stop(); + await watcher.stop(); }; return { diff --git a/yarn-project/end-to-end/src/fixtures/watcher.ts b/yarn-project/end-to-end/src/fixtures/watcher.ts new file mode 100644 index 00000000000..0d254fbf5ff --- /dev/null +++ b/yarn-project/end-to-end/src/fixtures/watcher.ts @@ -0,0 +1,64 @@ +import { type DebugLogger, type EthCheatCodes, createDebugLogger } from '@aztec/aztec.js'; +import { type EthAddress } from '@aztec/circuits.js'; +import { RunningPromise } from '@aztec/foundation/running-promise'; +import { RollupAbi } from '@aztec/l1-artifacts'; + +import { type GetContractReturnType, type HttpTransport, type PublicClient, getAddress, getContract } from 'viem'; +import type * as chains from 'viem/chains'; + +export class Watcher { + private rollup: GetContractReturnType>; + + private filledRunningPromise?: RunningPromise; + + private logger: DebugLogger = createDebugLogger(`aztec:utils:watcher`); + + constructor( + private cheatcodes: EthCheatCodes, + rollupAddress: EthAddress, + publicClient: PublicClient, + ) { + this.rollup = getContract({ + address: getAddress(rollupAddress.toString()), + abi: RollupAbi, + client: publicClient, + }); + + this.logger.info(`Watcher created for rollup at ${rollupAddress}`); + } + + start() { + if (this.filledRunningPromise) { + throw new Error('Watcher already watching for filled slot'); + } + this.filledRunningPromise = new RunningPromise(() => this.mineIfSlotFilled(), 1000); + this.filledRunningPromise.start(); + this.logger.info(`Watcher started`); + } + + async stop() { + await this.filledRunningPromise?.stop(); + } + + async mineIfSlotFilled() { + try { + const currentSlot = await this.rollup.read.getCurrentSlot(); + const pendingBlockNumber = BigInt(await this.rollup.read.pendingBlockCount()) - 1n; + const [, , lastSlotNumber] = await this.rollup.read.blocks([pendingBlockNumber]); + + if (currentSlot === lastSlotNumber) { + // We should jump to the next slot + const timestamp = await this.rollup.read.getTimestampForSlot([currentSlot + 1n]); + try { + await this.cheatcodes.warp(Number(timestamp)); + } catch (e) { + this.logger.error(`Failed to warp to timestamp ${timestamp}: ${e}`); + } + + this.logger.info(`Slot ${currentSlot} was filled, jumped to next slot`); + } + } catch (err) { + this.logger.error('mineIfSlotFilled failed', err); + } + } +} diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 7f034f51296..2d9a5029351 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -63,7 +63,6 @@ export type EnvVar = | 'SEQ_PUBLISHER_PRIVATE_KEY' | 'SEQ_REQUIRED_CONFIRMATIONS' | 'SEQ_PUBLISH_RETRY_INTERVAL_MS' - | 'TIME_TRAVELER' | 'VERSION' | 'SEQ_DISABLED' | 'PROVER_DISABLED' diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index b31fdd3b251..bfe5eb42943 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -1,5 +1,5 @@ import { type L1ReaderConfig, NULL_KEY } from '@aztec/ethereum'; -import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config'; +import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config'; /** * The configuration of the rollup transaction publisher. @@ -24,11 +24,6 @@ export interface PublisherConfig { * The interval to wait between publish retries. */ l1PublishRetryIntervalMS: number; - /** - * Whether the publisher is a time traveler and can warp the underlying chain - * @todo #8153 - Remove this flag once the time traveler is removed - */ - timeTraveler: boolean; } export const getTxSenderConfigMappings: ( @@ -69,11 +64,6 @@ export const getPublisherConfigMappings: (scope: 'PROVER' | 'SEQ') => ConfigMapp defaultValue: 1000, description: 'The interval to wait between publish retries.', }, - timeTraveler: { - env: `TIME_TRAVELER`, - description: 'Whether the publisher is a time traveler and can warp the underlying chain', - ...booleanConfigHelper(), - }, }); export function getPublisherConfigFromEnv(scope: 'PROVER' | 'SEQ'): PublisherConfig { diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index 33e0dcc7325..5fbce74c286 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -1,4 +1,4 @@ -import { L2Block } from '@aztec/circuit-types'; +import { L2Block, type ViemSignature } from '@aztec/circuit-types'; import { EthAddress } from '@aztec/circuits.js'; import { sleep } from '@aztec/foundation/sleep'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -27,7 +27,7 @@ class MockAvailabilityOracle { interface MockPublicClient { getTransactionReceipt: ({ hash }: { hash: '0x${string}' }) => Promise; - getBlock(): Promise<{ timestamp: number }>; + getBlock(): Promise<{ timestamp: bigint }>; getTransaction: ({ hash }: { hash: '0x${string}' }) => Promise<{ input: `0x${string}`; hash: `0x${string}` }>; } @@ -46,6 +46,15 @@ interface MockRollupContractWrite { interface MockRollupContractRead { archive: () => Promise<`0x${string}`>; getCurrentSlot(): Promise; + validateHeader: ( + args: readonly [ + `0x${string}`, + ViemSignature[], + `0x${string}`, + bigint, + { ignoreDA: boolean; ignoreSignatures: boolean }, + ], + ) => Promise; } class MockRollupContract { @@ -131,7 +140,6 @@ describe('L1Publisher', () => { rollupAddress: EthAddress.ZERO.toString(), }, l1PublishRetryIntervalMS: 1, - timeTraveller: false, } as unknown as TxSenderConfig & PublisherConfig; publisher = new L1Publisher(config, new NoopTelemetryClient()); @@ -143,6 +151,7 @@ describe('L1Publisher', () => { account = (publisher as any)['account']; rollupContractRead.getCurrentSlot.mockResolvedValue(l2Block.header.globalVariables.slotNumber.toBigInt()); + publicClient.getBlock.mockResolvedValue({ timestamp: 12n }); }); it('publishes and process l2 block to l1', async () => { @@ -161,7 +170,9 @@ describe('L1Publisher', () => { `0x${blockHash.toString('hex')}`, `0x${body.toString('hex')}`, ] as const; - expect(rollupContractSimulate.publishAndProcess).toHaveBeenCalledWith(args, { account: account }); + if (!L1Publisher.SKIP_SIMULATION) { + expect(rollupContractSimulate.publishAndProcess).toHaveBeenCalledWith(args, { account: account }); + } expect(rollupContractWrite.publishAndProcess).toHaveBeenCalledWith(args, { account: account }); expect(publicClient.getTransactionReceipt).toHaveBeenCalledWith({ hash: publishAndProcessTxHash }); }); @@ -181,7 +192,9 @@ describe('L1Publisher', () => { `0x${archive.toString('hex')}`, `0x${blockHash.toString('hex')}`, ] as const; - expect(rollupContractSimulate.process).toHaveBeenCalledWith(args, { account }); + if (!L1Publisher.SKIP_SIMULATION) { + expect(rollupContractSimulate.process).toHaveBeenCalledWith(args, { account }); + } expect(rollupContractWrite.process).toHaveBeenCalledWith(args, { account }); expect(publicClient.getTransactionReceipt).toHaveBeenCalledWith({ hash: processTxHash }); }); @@ -208,10 +221,18 @@ describe('L1Publisher', () => { rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); rollupContractSimulate.publishAndProcess.mockRejectedValueOnce(new Error()); + if (L1Publisher.SKIP_SIMULATION) { + rollupContractRead.validateHeader.mockRejectedValueOnce(new Error('Test error')); + } + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); - expect(rollupContractSimulate.publishAndProcess).toHaveBeenCalledTimes(1); + if (!L1Publisher.SKIP_SIMULATION) { + expect(rollupContractSimulate.publishAndProcess).toHaveBeenCalledTimes(1); + } + expect(rollupContractRead.validateHeader).toHaveBeenCalledTimes(1); + expect(rollupContractWrite.publishAndProcess).toHaveBeenCalledTimes(0); }); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 9ec67f80d94..9bb8316dd08 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,14 +1,6 @@ -import { EthCheatCodes } from '@aztec/aztec.js'; import { type L2Block, type Signature } from '@aztec/circuit-types'; import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; -import { - AZTEC_SLOT_DURATION, - ETHEREUM_SLOT_DURATION, - EthAddress, - GENESIS_ARCHIVE_ROOT, - type Header, - type Proof, -} from '@aztec/circuits.js'; +import { ETHEREUM_SLOT_DURATION, EthAddress, GENESIS_ARCHIVE_ROOT, type Header, type Proof } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -103,15 +95,6 @@ export type MetadataForSlot = { archive: Buffer; }; -// @note If we want to simulate in the future, we have to skip the viem simulations and use `reads` instead -// This is because the viem simulations are not able to simulate the future, only the current state. -// This means that we will be simulating as if `block.timestamp` is the same for the next block -// as for the last block. -// Nevertheless, it can be quite useful for figuring out why exactly the transaction is failing -// as a middle ground right now, we will be skipping the simulation and just sending the transaction -// but only after we have done a successful run of the `validateHeader` for the timestamp in the future. -const SKIP_SIMULATION = true; - /** * Publishes L2 blocks to L1. This implementation does *not* retry a transaction in * the event of network congestion, but should work for local development. @@ -121,9 +104,17 @@ const SKIP_SIMULATION = true; * Adapted from https://github.com/AztecProtocol/aztec2-internal/blob/master/falafel/src/rollup_publisher.ts. */ export class L1Publisher { + // @note If we want to simulate in the future, we have to skip the viem simulations and use `reads` instead + // This is because the viem simulations are not able to simulate the future, only the current state. + // This means that we will be simulating as if `block.timestamp` is the same for the next block + // as for the last block. + // Nevertheless, it can be quite useful for figuring out why exactly the transaction is failing + // as a middle ground right now, we will be skipping the simulation and just sending the transaction + // but only after we have done a successful run of the `validateHeader` for the timestamp in the future. + public static SKIP_SIMULATION = true; + private interruptibleSleep = new InterruptibleSleep(); private sleepTimeMs: number; - private timeTraveler: boolean; private interrupted = false; private metrics: L1PublisherMetrics; private log = createDebugLogger('aztec:sequencer:publisher'); @@ -139,11 +130,8 @@ export class L1Publisher { private publicClient: PublicClient; private account: PrivateKeyAccount; - private ethCheatCodes: EthCheatCodes; - constructor(config: TxSenderConfig & PublisherConfig, client: TelemetryClient) { this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000; - this.timeTraveler = config?.timeTraveler ?? false; this.metrics = new L1PublisherMetrics(client, 'L1Publisher'); const { l1RpcUrl: rpcUrl, l1ChainId: chainId, publisherPrivateKey, l1Contracts } = config; @@ -170,22 +158,21 @@ export class L1Publisher { abi: RollupAbi, client: walletClient, }); - - this.ethCheatCodes = new EthCheatCodes(rpcUrl); - } - - public async amIAValidator(): Promise { - return await this.rollupContract.read.isValidator([this.account.address]); - } - - public async getValidatorCount(): Promise { - return BigInt(await this.rollupContract.read.getValidatorCount()); } public getSenderAddress(): Promise { return Promise.resolve(EthAddress.fromString(this.account.address)); } + /** + * @notice Calls `canProposeAtTime` with the time of the next Ethereum block and the sender address + * + * @dev Throws if unable to propose + * + * @param archive - The archive that we expect to be current state + * @return slot - The L2 slot number of the next Ethereum block, + * @return blockNumber - The L2 block number of the next L2 block + */ public async canProposeAtNextEthBlock(archive: Buffer): Promise<[bigint, bigint]> { const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); const [slot, blockNumber] = await this.rollupContract.read.canProposeAtTime([ @@ -200,7 +187,7 @@ export class L1Publisher { header: Header, digest: Buffer = new Fr(GENESIS_ARCHIVE_ROOT).toBuffer(), attestations: Signature[] = [], - ): Promise { + ): Promise { const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); const formattedAttestations = attestations.map(attest => attest.toViemSignature()); @@ -216,6 +203,7 @@ export class L1Publisher { try { await this.rollupContract.read.validateHeader(args, { account: this.account }); + return true; } catch (error: unknown) { // Specify the type of error if (error instanceof ContractFunctionRevertedError) { @@ -224,7 +212,7 @@ export class L1Publisher { } else { this.log.debug(`Unexpected error during validation: ${error}`); } - throw error; // Re-throw the error if needed + return false; } } @@ -287,7 +275,9 @@ export class L1Publisher { // This means that we can avoid the simulation issues in later checks. // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which // make time consistency checks break. - await this.validateBlockForSubmission(block.header, block.archive.root.toBuffer(), attestations); + if (!(await this.validateBlockForSubmission(block.header, block.archive.root.toBuffer(), attestations))) { + return false; + } const processTxArgs = { header: block.header.toBuffer(), @@ -332,8 +322,6 @@ export class L1Publisher { this.log.info(`Published L2 block to L1 rollup contract`, { ...stats, ...ctx }); this.metrics.recordProcessBlockTx(timer.ms(), stats); - await this.commitTimeJump(block.header.globalVariables.slotNumber.toBigInt() + 1n); - return true; } @@ -347,49 +335,6 @@ export class L1Publisher { return false; } - async commitTimeJump(slot: bigint) { - // @note So, we are cheating a bit here. Since the tests are running anvil auto-mine - // no blocks are coming around unless we do something, and since we cannot push - // more blocks within the same slot (when `IS_DEV_NET = false`), we can just - // fast forward the anvil chain such that the next block will be the one we need. - // this means that we are forwarding to time of the next slot - 12 seconds such that - // the NEXT ethereum block will be within the new slot. - // If the slot duration of L2 is just 1 L1 slot, then this will not do anything, as - // the time to jump to is current time. - // - // Time jumps only allowed into the future. - // - // If this is run on top of a real chain, the time lords will catch you. - // - // @todo #8153 - - if (!this.timeTraveler) { - return; - } - - // If the aztec slot duration is same length as the ethereum slot duration, we don't need to do anything - if ((ETHEREUM_SLOT_DURATION as number) === (AZTEC_SLOT_DURATION as number)) { - return; - } - - const [currentTime, timeStampForSlot] = await Promise.all([ - this.ethCheatCodes.timestamp(), - this.rollupContract.read.getTimestampForSlot([slot]), - ]); - - // @note We progress the time to the next slot AND mine the block. - // This means that the next effective block will be ETHEREUM_SLOT_DURATION after that. - // This will cause issues if slot duration is equal to one (1) L1 slot, and sequencer selection is run - // The reason is that simulations on ANVIL cannot be run with timestamp + x, so we need to "BE" there. - // @todo #8110 - const timestamp = timeStampForSlot; // - BigInt(ETHEREUM_SLOT_DURATION); - - if (timestamp > currentTime) { - this.log.info(`Committing time jump to slot ${slot}`); - await this.ethCheatCodes.warp(Number(timestamp)); - } - } - public async submitProof( header: Header, archiveRoot: Fr, @@ -472,7 +417,7 @@ export class L1Publisher { `0x${proof.toString('hex')}`, ] as const; - if (!SKIP_SIMULATION) { + if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.submitBlockRootProof(args, { account: this.account, }); @@ -520,7 +465,7 @@ export class L1Publisher { attestations, ] as const; - if (!SKIP_SIMULATION) { + if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.process(args, { account: this.account }); } @@ -534,7 +479,7 @@ export class L1Publisher { `0x${encodedData.blockHash.toString('hex')}`, ] as const; - if (!SKIP_SIMULATION) { + if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.process(args, { account: this.account }); } return await this.rollupContract.write.process(args, { @@ -561,7 +506,7 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - if (!SKIP_SIMULATION) { + if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.publishAndProcess(args, { account: this.account, }); @@ -578,7 +523,7 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - if (!SKIP_SIMULATION) { + if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.publishAndProcess(args, { account: this.account, }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 9ee5c089474..24a52633326 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -41,7 +41,7 @@ import { type MockProxy, mock, mockFn } from 'jest-mock-extended'; import { type BlockBuilderFactory } from '../block_builder/index.js'; import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js'; -import { type L1Publisher, type MetadataForSlot } from '../publisher/l1-publisher.js'; +import { type L1Publisher } from '../publisher/l1-publisher.js'; import { TxValidatorFactory } from '../tx_validator/tx_validator_factory.js'; import { Sequencer } from './sequencer.js'; @@ -89,24 +89,19 @@ describe('sequencer', () => { }; let block: L2Block; - let metadata: MetadataForSlot; beforeEach(() => { lastBlockNumber = 0; block = L2Block.random(lastBlockNumber + 1); - metadata = { - proposer: EthAddress.ZERO, - slot: block.header.globalVariables.slotNumber.toBigInt(), - pendingBlockNumber: BigInt(lastBlockNumber), - archive: block.header.lastArchive.toBuffer(), - }; - publisher = mock(); publisher.getCurrentEpochCommittee.mockResolvedValue(committee); - publisher.getMetadataForSlotAtNextEthBlock.mockResolvedValue(metadata); - publisher.getValidatorCount.mockResolvedValue(0n); + publisher.canProposeAtNextEthBlock.mockResolvedValue([ + block.header.globalVariables.slotNumber.toBigInt(), + block.header.globalVariables.blockNumber.toBigInt(), + ]); + publisher.validateBlockForSubmission.mockResolvedValue(true); globalVariableBuilder = mock(); merkleTreeOps = mock(); @@ -212,6 +207,7 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); + // Ok, we have an issue that we never actually call the process L2 block expect(publisher.processL2Block).toHaveBeenCalledTimes(1); expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); @@ -227,7 +223,7 @@ describe('sequencer', () => { provingPromise: Promise.resolve(result), }; - p2p.getTxs.mockReturnValueOnce([tx]); + p2p.getTxs.mockReturnValue([tx]); blockSimulator.startNewBlock.mockResolvedValueOnce(ticket); blockSimulator.finaliseBlock.mockResolvedValue({ block }); publisher.processL2Block.mockResolvedValueOnce(true); @@ -243,21 +239,28 @@ describe('sequencer', () => { gasFees, ); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); + globalVariableBuilder.buildGlobalVariables.mockResolvedValue(mockedGlobalVariables); // Not your turn! - const publisherAddress = EthAddress.random(); - publisher.getSenderAddress.mockResolvedValue(publisherAddress); - publisher.getMetadataForSlotAtNextEthBlock.mockResolvedValue({ ...metadata, proposer: EthAddress.random() }); - // Specify that there is a validator, such that we don't allow everyone to publish - publisher.getValidatorCount.mockResolvedValueOnce(1n); + publisher.canProposeAtNextEthBlock.mockRejectedValue(new Error()); + publisher.validateBlockForSubmission.mockResolvedValue(false); await sequencer.initialSync(); await sequencer.work(); expect(blockSimulator.startNewBlock).not.toHaveBeenCalled(); + // Now we can propose, but lets assume that the content is still "bad" (missing sigs etc) + publisher.canProposeAtNextEthBlock.mockResolvedValue([ + block.header.globalVariables.slotNumber.toBigInt(), + block.header.globalVariables.blockNumber.toBigInt(), + ]); + + await sequencer.work(); + expect(blockSimulator.startNewBlock).not.toHaveBeenCalled(); + // Now it is! - publisher.getMetadataForSlotAtNextEthBlock.mockResolvedValue({ ...metadata, proposer: publisherAddress }); + publisher.validateBlockForSubmission.mockClear(); + publisher.validateBlockForSubmission.mockResolvedValue(true); await sequencer.work(); expect(blockSimulator.startNewBlock).toHaveBeenCalledWith( @@ -627,13 +630,11 @@ describe('sequencer', () => { await sequencer.initialSync(); - l2BlockSource.getBlockNumber - // let it work for a bit - .mockResolvedValueOnce(lastBlockNumber) - .mockResolvedValueOnce(lastBlockNumber) - .mockResolvedValueOnce(lastBlockNumber) - // then tell it to abort - .mockResolvedValue(lastBlockNumber + 1); + // This could practically be for any reason, e.g., could also be that we have entered a new slot. + publisher.validateBlockForSubmission + .mockResolvedValueOnce(true) + .mockResolvedValueOnce(true) + .mockResolvedValueOnce(false); await sequencer.work(); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 122df289b8d..2b8fa1ac1bf 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -389,6 +389,10 @@ export class Sequencer { proposalHeader: Header, historicalHeader: Header | undefined, ): Promise { + if (!(await this.publisher.validateBlockForSubmission(proposalHeader))) { + return; + } + const newGlobalVariables = proposalHeader.globalVariables; this.metrics.recordNewBlock(newGlobalVariables.blockNumber.toNumber(), validTxs.length); @@ -422,8 +426,8 @@ export class Sequencer { await this.p2pClient.deleteTxs(Tx.getHashes(failedTxData)); } - await this.publisher.validateBlockForSubmission(proposalHeader); if ( + !(await this.publisher.validateBlockForSubmission(proposalHeader)) || !this.shouldProposeBlock(historicalHeader, { validTxsCount: validTxs.length, processedTxsCount: processedTxs.length, @@ -447,7 +451,9 @@ export class Sequencer { // Block is ready, now finalise const { block } = await blockBuilder.finaliseBlock(); - await this.publisher.validateBlockForSubmission(block.header); + if (!(await this.publisher.validateBlockForSubmission(block.header))) { + return; + } const workDuration = workTimer.ms(); this.log.verbose( From 33889666567cbfe418822998c6d8b53bfbc825ea Mon Sep 17 00:00:00 2001 From: LHerskind Date: Wed, 28 Aug 2024 20:19:42 +0000 Subject: [PATCH 03/26] feat: revert if timestamp in future --- l1-contracts/src/core/Rollup.sol | 54 +++++++++++++--------- l1-contracts/src/core/libraries/Errors.sol | 2 +- l1-contracts/test/Rollup.t.sol | 16 +++++++ 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 02a3bdda097..c15862dfe46 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -444,31 +444,10 @@ contract Rollup is Leonidas, IRollup, ITestRollup { uint256 _currentTime, DataStructures.ExecutionFlags memory _flags ) external view override(IRollup) { - // @note This is a convenience function to allow for easier testing of the header validation - // without having to go through the entire process of submitting a block. - // This is not used in production code. - HeaderLib.Header memory header = HeaderLib.decode(_header); _validateHeader(header, _signatures, _digest, _currentTime, _flags); } - function _validateHeader( - HeaderLib.Header memory _header, - SignatureLib.Signature[] memory _signatures, - bytes32 _digest, - uint256 _currentTime, - DataStructures.ExecutionFlags memory _flags - ) internal view { - // @note This is a convenience function to allow for easier testing of the header validation - // without having to go through the entire process of submitting a block. - // This is not used in production code. - - _validateHeaderForSubmissionBase(_header, _currentTime, _flags); - _validateHeaderForSubmissionSequencerSelection( - _header.globalVariables.slotNumber, _signatures, _digest, _currentTime, _flags - ); - } - /** * @notice Processes an incoming L2 block with signatures * @@ -589,6 +568,29 @@ contract Rollup is Leonidas, IRollup, ITestRollup { } } + /** + * @notice Validates the header for submission + * + * @param _header - The proposed block header + * @param _signatures - The signatures for the attestations + * @param _digest - The digest that signatures signed + * @param _currentTime - The time of execution + * @dev - This value is provided to allow for simple simulation of future + * @param _flags - Flags specific to the execution, whether certain checks should be skipped + */ + function _validateHeader( + HeaderLib.Header memory _header, + SignatureLib.Signature[] memory _signatures, + bytes32 _digest, + uint256 _currentTime, + DataStructures.ExecutionFlags memory _flags + ) internal view { + _validateHeaderForSubmissionBase(_header, _currentTime, _flags); + _validateHeaderForSubmissionSequencerSelection( + _header.globalVariables.slotNumber, _signatures, _digest, _currentTime, _flags + ); + } + /** * @notice Validate a header for submission to the pending chain (sequencer selection checks) * @@ -703,6 +705,16 @@ contract Rollup is Leonidas, IRollup, ITestRollup { revert Errors.Rollup__InvalidTimestamp(timestamp, _header.globalVariables.timestamp); } + if (timestamp > _currentTime) { + // @note If you are hitting this error, it is likely because the chain you use have a blocktime that differs + // from the value that we have in the constants. + // When you are encountering this, it will likely be as the sequencer expects to be able to include + // an Aztec block in the "next" ethereum block based on a timestamp that is 12 seconds in the future + // from the last block. However, if the actual will only be 1 second in the future, you will end up + // expecting this value to be in the future. + revert Errors.Rollup__TimestampInFuture(_currentTime, timestamp); + } + // Check if the data is available using availability oracle (change availability oracle if you want a different DA layer) if ( !_flags.ignoreDA && !AVAILABILITY_ORACLE.isAvailable(_header.contentCommitment.txsEffectsHash) diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 257d7695707..b7ff5d9b4e6 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -56,7 +56,7 @@ library Errors { error Rollup__InvalidChainId(uint256 expected, uint256 actual); // 0x37b5bc12 error Rollup__InvalidVersion(uint256 expected, uint256 actual); // 0x9ef30794 error Rollup__InvalidTimestamp(uint256 expected, uint256 actual); // 0x3132e895 - error Rollup__TimestampInFuture(); // 0xbc1ce916 + error Rollup__TimestampInFuture(uint256 max, uint256 actual); // 0x89f30690 error Rollup__TimestampTooOld(); // 0x72ed9c81 error Rollup__UnavailableTxs(bytes32 txsHash); // 0x414906c3 error Rollup__NothingToPrune(); // 0x850defd3 diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index cd7de61110e..07c67385a80 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -78,6 +78,19 @@ contract RollupTest is DecoderBase { _; } + function testTimestamp() public setUpFor("mixed_block_1") { + // Ensure that the timestamp of the current slot is never in the future. + for (uint256 i = 0; i < 100; i++) { + uint256 slot = rollup.getCurrentSlot(); + uint256 ts = rollup.getTimestampForSlot(slot); + + assertLe(ts, block.timestamp, "Invalid timestamp"); + + vm.warp(block.timestamp + 12); + vm.roll(block.number + 1); + } + } + function testRevertPrune() public setUpFor("mixed_block_1") { if (rollup.isDevNet()) { vm.expectRevert(abi.encodeWithSelector(Errors.DevNet__NoPruningAllowed.selector)); @@ -182,6 +195,9 @@ contract RollupTest is DecoderBase { uint256 portalBalance = portalERC20.balanceOf(address(feeJuicePortal)); + // We jump to the time of the block. (unless it is in the past) + vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); + vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientBalance.selector, From 13a60a3d7c9a4035b08f2aa68ff90d3fa1d01a07 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 29 Aug 2024 15:07:50 +0000 Subject: [PATCH 04/26] feat: including txhashes explicitly in the rollup attestations --- l1-contracts/src/core/Rollup.sol | 12 +++++++++--- l1-contracts/src/core/interfaces/IRollup.sol | 2 ++ l1-contracts/src/core/libraries/ConstantsGen.sol | 2 +- l1-contracts/test/sparta/Sparta.t.sol | 7 ++++++- .../crates/types/src/constants.nr | 2 +- .../circuit-types/src/p2p/block_proposal.ts | 8 +++++++- yarn-project/circuits.js/src/constants.gen.ts | 2 +- .../end-to-end/src/e2e_p2p_network.test.ts | 6 ++++-- yarn-project/end-to-end/src/fixtures/utils.ts | 1 + .../src/publisher/l1-publisher.ts | 16 ++++++++++++++-- .../sequencer-client/src/sequencer/sequencer.ts | 16 +++++++++++----- .../src/duties/validation_service.ts | 10 +++++++--- 12 files changed, 64 insertions(+), 20 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index c15862dfe46..7a78f79057f 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -208,11 +208,12 @@ contract Rollup is Leonidas, IRollup, ITestRollup { bytes calldata _header, bytes32 _archive, bytes32 _blockHash, + bytes32[] memory _txHashes, SignatureLib.Signature[] memory _signatures, bytes calldata _body ) external override(IRollup) { AVAILABILITY_ORACLE.publish(_body); - process(_header, _archive, _blockHash, _signatures); + process(_header, _archive, _blockHash, _txHashes, _signatures); } /** @@ -460,15 +461,19 @@ contract Rollup is Leonidas, IRollup, ITestRollup { bytes calldata _header, bytes32 _archive, bytes32 _blockHash, + bytes32[] memory _txHashes, SignatureLib.Signature[] memory _signatures ) public override(IRollup) { // Decode and validate header HeaderLib.Header memory header = HeaderLib.decode(_header); setupEpoch(); + + // TODO: make function for this + bytes32 digest = keccak256(abi.encodePacked(_archive, _txHashes)); _validateHeader({ _header: header, _signatures: _signatures, - _digest: _archive, + _digest: digest, _currentTime: block.timestamp, _flags: DataStructures.ExecutionFlags({ignoreDA: false, ignoreSignatures: false}) }); @@ -525,7 +530,8 @@ contract Rollup is Leonidas, IRollup, ITestRollup { override(IRollup) { SignatureLib.Signature[] memory emptySignatures = new SignatureLib.Signature[](0); - process(_header, _archive, _blockHash, emptySignatures); + bytes32[] memory emptyTxHashes = new bytes32[](0); + process(_header, _archive, _blockHash, emptyTxHashes, emptySignatures); } /** diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index 4e129e052b5..0b571ca6c39 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -43,6 +43,7 @@ interface IRollup { bytes calldata _header, bytes32 _archive, bytes32 _blockHash, + bytes32[] memory _txHashes, SignatureLib.Signature[] memory _signatures, bytes calldata _body ) external; @@ -57,6 +58,7 @@ interface IRollup { bytes calldata _header, bytes32 _archive, bytes32 _blockHash, + bytes32[] memory _txHashes, SignatureLib.Signature[] memory _signatures ) external; diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 2e04e93dfe2..a1e9567a747 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -104,7 +104,7 @@ library Constants { uint256 internal constant ETHEREUM_SLOT_DURATION = 12; uint256 internal constant AZTEC_SLOT_DURATION = 12; uint256 internal constant AZTEC_EPOCH_DURATION = 48; - uint256 internal constant IS_DEV_NET = 1; + uint256 internal constant IS_DEV_NET = 0; uint256 internal constant GENESIS_ARCHIVE_ROOT = 8142738430000951296386584486068033372964809139261822027365426310856631083550; uint256 internal constant FEE_JUICE_INITIAL_MINT = 20000000000; diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index 028533839d2..b8c8af4079d 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -165,6 +165,8 @@ contract SpartaTest is DecoderBase { DecoderBase.Full memory full = load(_name); bytes memory header = full.block.header; bytes32 archive = full.block.archive; + // TODO(md): get the tx hashes from the block - but we do not have them now + // Come back to this bytes memory body = full.block.body; StructToAvoidDeepStacks memory ree; @@ -217,8 +219,11 @@ contract SpartaTest is DecoderBase { ree.shouldRevert = true; } + // TODO(md): this is temp and probably will not pass + bytes32[] memory txHashes = new bytes32[](0); + vm.prank(ree.proposer); - rollup.process(header, archive, bytes32(0), signatures); + rollup.process(header, archive, bytes32(0), txHashes, signatures); if (ree.shouldRevert) { return; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr index 2367626358b..398db5d31b7 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -137,7 +137,7 @@ global ETHEREUM_SLOT_DURATION: u32 = 12; // AZTEC_SLOT_DURATION should be a multiple of ETHEREUM_SLOT_DURATION global AZTEC_SLOT_DURATION: u32 = ETHEREUM_SLOT_DURATION * 1; global AZTEC_EPOCH_DURATION: u32 = 48; -global IS_DEV_NET: bool = true; +global IS_DEV_NET: bool = false; // The following is taken from building a block and looking at the `lastArchive` value in it. // You can run the `integration_l1_publisher.test.ts` and look at the first blocks in the fixtures. global GENESIS_ARCHIVE_ROOT: Field = 0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e; diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.ts b/yarn-project/circuit-types/src/p2p/block_proposal.ts index 5c77de9b5e9..0d8c7514b08 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.ts @@ -36,15 +36,17 @@ export class BlockProposal extends Gossipable { /** The sequence of transactions in the block */ public readonly txs: TxHash[], /** The signer of the BlockProposal over the header of the new block*/ - public readonly signature: Signature, + public readonly signature: Signature ) { super(); } + static { this.p2pTopic = createTopicString(TopicType.block_proposal); } + override p2pMessageIdentifier(): Buffer32 { return BlockProposalHash.fromField(this.archive); } @@ -66,6 +68,10 @@ export class BlockProposal extends Gossipable { return this.sender; } + getPayload() { + return serializeToBuffer([this.archive, this.txs]); + } + toBuffer(): Buffer { return serializeToBuffer([this.header, this.archive, this.txs.length, this.txs, this.signature]); } diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 1b25acd8207..98f38ea7a4e 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -90,7 +90,7 @@ export const BLOB_SIZE_IN_BYTES = 126976; export const ETHEREUM_SLOT_DURATION = 12; export const AZTEC_SLOT_DURATION = 12; export const AZTEC_EPOCH_DURATION = 48; -export const IS_DEV_NET = 1; +export const IS_DEV_NET = 0; export const GENESIS_ARCHIVE_ROOT = 8142738430000951296386584486068033372964809139261822027365426310856631083550n; export const FEE_JUICE_INITIAL_MINT = 20000000000; export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 20000; diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index f297b084b47..ad494f2668f 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -35,7 +35,7 @@ describe('e2e_p2p_network', () => { beforeEach(async () => { // If we want to test with interval mining, we can use the local host and start `anvil --block-time 12` - const useLocalHost = false; + const useLocalHost = true; if (useLocalHost) { jest.setTimeout(300_000); } @@ -49,7 +49,9 @@ describe('e2e_p2p_network', () => { // Add 1 extra validator if in devnet or NUM_NODES if not. // Each of these will become a validator and sign attestations. + console.log('IS_DEV_NET', IS_DEV_NET); const limit = IS_DEV_NET ? 1 : NUM_NODES; + console.log('limit', limit); for (let i = 0; i < limit; i++) { const account = privateKeyToAccount(`0x${getPrivateKeyFromIndex(i + 1)!.toString('hex')}`); initialValidators.push(EthAddress.fromString(account.address)); @@ -72,7 +74,7 @@ describe('e2e_p2p_network', () => { } }); - it('should rollup txs from all peers', async () => { + it.only('should rollup txs from all peers', async () => { // create the bootstrap node for the network if (!bootstrapNodeEnr) { throw new Error('Bootstrap node ENR is not available'); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 7fb9bf3f5b1..3e3e94b2b1a 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -461,6 +461,7 @@ export async function setup( const wallets = numberOfAccounts > 0 ? await createAccounts(pxe, numberOfAccounts) : []; const cheatCodes = CheatCodes.create(config.l1RpcUrl, pxe!); + console.log('made account'); const teardown = async () => { if (aztecNode instanceof AztecNodeService) { diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 9bb8316dd08..aa1cb70b129 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,4 +1,4 @@ -import { type L2Block, type Signature } from '@aztec/circuit-types'; +import { type L2Block, type Signature, TxHash } from '@aztec/circuit-types'; import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; import { ETHEREUM_SLOT_DURATION, EthAddress, GENESIS_ARCHIVE_ROOT, type Header, type Proof } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; @@ -70,6 +70,8 @@ export type L1ProcessArgs = { blockHash: Buffer; /** L2 block body. */ body: Buffer; + /** L2 block tx hashes */ + txHashes: TxHash[]; /** Attestations */ attestations?: Signature[]; }; @@ -228,6 +230,11 @@ export class L1Publisher { this.rollupContract.read.archive(), ]); + console.log('metadata for the next eth block'); + console.table({ + slot, + pendingBlockNumber: pendingBlockCount - 1n, + }); return { proposer: EthAddress.fromString(submitter), slot, @@ -264,7 +271,7 @@ export class L1Publisher { * @param block - L2 block to publish. * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise. */ - public async processL2Block(block: L2Block, attestations?: Signature[]): Promise { + public async processL2Block(block: L2Block, attestations?: Signature[], txHashes?: TxHash[]): Promise { const ctx = { blockNumber: block.number, slotNumber: block.header.globalVariables.slotNumber.toBigInt(), @@ -285,6 +292,7 @@ export class L1Publisher { blockHash: block.header.hash().toBuffer(), body: block.body.toBuffer(), attestations, + txHashes: txHashes ?? [], // NTS(md): should be 32 bytes? }; // Process block and publish the body if needed (if not already published) @@ -458,10 +466,12 @@ export class L1Publisher { try { if (encodedData.attestations) { const attestations = encodedData.attestations.map(attest => attest.toViemSignature()); + const txHashes = encodedData.txHashes.map(txHash => txHash.to0xString()); const args = [ `0x${encodedData.header.toString('hex')}`, `0x${encodedData.archive.toString('hex')}`, `0x${encodedData.blockHash.toString('hex')}`, + txHashes, attestations, ] as const; @@ -498,10 +508,12 @@ export class L1Publisher { try { if (encodedData.attestations) { const attestations = encodedData.attestations.map(attest => attest.toViemSignature()); + const txHashes = encodedData.txHashes.map(txHash => txHash.to0xString()); const args = [ `0x${encodedData.header.toString('hex')}`, `0x${encodedData.archive.toString('hex')}`, `0x${encodedData.blockHash.toString('hex')}`, + txHashes, attestations, `0x${encodedData.body.toString('hex')}`, ] as const; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 2b8fa1ac1bf..8e938fd4cb2 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -6,6 +6,7 @@ import { type ProcessedTx, Signature, Tx, + TxHash, type TxValidator, } from '@aztec/circuit-types'; import { type AllowedElement, BlockProofError, PROVING_STATUS } from '@aztec/circuit-types/interfaces'; @@ -473,8 +474,11 @@ export class Sequencer { this.log.verbose(`Flushing completed`); } + const txHashes = validTxs.map(tx => tx.getTxHash()); + this.isFlushing = false; - const attestations = await this.collectAttestations(block); + this.log.verbose('SEQUENCER | collectAttestations'); + const attestations = await this.collectAttestations(block, txHashes); try { await this.publishL2Block(block, attestations); @@ -495,7 +499,7 @@ export class Sequencer { this.isFlushing = true; } - protected async collectAttestations(block: L2Block): Promise { + protected async collectAttestations(block: L2Block, txHashes: TxHash[]): Promise { // @todo This should collect attestations properly and fix the ordering of them to make sense // the current implementation is a PLACEHOLDER and should be nuked from orbit. // It is assuming that there will only be ONE (1) validator, so only one attestation @@ -510,6 +514,8 @@ export class Sequencer { // / \ // _____________/_ __ \_____________ + console.log('SEQUENCER | IS_DEV_NET', IS_DEV_NET); + console.log('SEQUENCER | this.validatorClient', this.validatorClient); if (IS_DEV_NET || !this.validatorClient) { return undefined; } @@ -526,7 +532,7 @@ export class Sequencer { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7974): we do not have transaction[] lists in the block for now // Dont do anything with the proposals for now - just collect them - const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, []); + const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txHashes); this.state = SequencerState.PUBLISHING_BLOCK_TO_PEERS; this.validatorClient.broadcastBlockProposal(proposal); @@ -545,11 +551,11 @@ export class Sequencer { @trackSpan('Sequencer.publishL2Block', block => ({ [Attributes.BLOCK_NUMBER]: block.number, })) - protected async publishL2Block(block: L2Block, attestations?: Signature[]) { + protected async publishL2Block(block: L2Block, attestations?: Signature[], txHashes?: TxHash[]) { // Publishes new block to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_BLOCK; - const publishedL2Block = await this.publisher.processL2Block(block, attestations); + const publishedL2Block = await this.publisher.processL2Block(block, attestations, txHashes); if (publishedL2Block) { this.lastPublishedBlock = block.number; } else { diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index 870f82d9520..da04ce8ac60 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -3,6 +3,7 @@ import { type Header } from '@aztec/circuits.js'; import { type Fr } from '@aztec/foundation/fields'; import { type ValidatorKeyStore } from '../key_store/interface.js'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; export class ValidationService { constructor(private keyStore: ValidatorKeyStore) {} @@ -18,8 +19,8 @@ export class ValidationService { */ async createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { // Note: just signing the archive for now - const archiveBuf = archive.toBuffer(); - const sig = await this.keyStore.sign(archiveBuf); + const payload = serializeToBuffer([archive, txs]); + const sig = await this.keyStore.sign(payload); return new BlockProposal(header, archive, txs, sig); } @@ -33,7 +34,10 @@ export class ValidationService { async attestToProposal(proposal: BlockProposal): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct - const buf = proposal.archive.toBuffer(); + // TODO: in the function before this, check that all of the txns exist in the payload + + console.log('attesting to proposal', proposal); + const buf = proposal.getPayload(); const sig = await this.keyStore.sign(buf); return new BlockAttestation(proposal.header, proposal.archive, sig); } From 86026f265e9496ca4d158dfc8d572b4681b7a185 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:24:18 +0000 Subject: [PATCH 05/26] temp --- l1-contracts/src/core/Rollup.sol | 1 + .../src/core/sequencer_selection/Leonidas.sol | 33 ++++++++-------- l1-contracts/test/sparta/Sparta.t.sol | 30 +++++++++++++++ .../end-to-end/src/e2e_p2p_network.test.ts | 17 +++++++-- yarn-project/end-to-end/src/fixtures/utils.ts | 2 + yarn-project/foundation/src/config/env_var.ts | 4 +- yarn-project/p2p/src/client/p2p_client.ts | 1 + .../p2p/src/service/libp2p_service.ts | 2 +- .../src/publisher/l1-publisher.ts | 27 ++++++++++--- .../src/sequencer/sequencer.ts | 23 +++++++++-- yarn-project/validator-client/src/config.ts | 19 +++++++++- .../validator-client/src/validator.ts | 38 +++++++++++++++++-- 12 files changed, 160 insertions(+), 37 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 7a78f79057f..eae17d00ba6 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -409,6 +409,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup { revert Errors.Rollup__SlotAlreadyInChain(lastSlot, slot); } + // Make sure that the proposer is up to date bytes32 tipArchive = archive(); if (tipArchive != _archive) { revert Errors.Rollup__InvalidArchive(tipArchive, _archive); diff --git a/l1-contracts/src/core/sequencer_selection/Leonidas.sol b/l1-contracts/src/core/sequencer_selection/Leonidas.sol index 709e6fad153..194c0fc098c 100644 --- a/l1-contracts/src/core/sequencer_selection/Leonidas.sol +++ b/l1-contracts/src/core/sequencer_selection/Leonidas.sol @@ -133,7 +133,7 @@ contract Leonidas is Ownable, ILeonidas { return epochs[_epoch].committee; } - function getCommitteeAt(uint256 _ts) internal view returns (address[] memory) { + function getCommitteeAt(uint256 _ts) public view returns (address[] memory) { uint256 epochNumber = getEpochAt(_ts); if (epochNumber == 0) { return new address[](0); @@ -161,9 +161,6 @@ contract Leonidas is Ownable, ILeonidas { /** * @notice Get the validator set for the current epoch - * - * @dev Makes a call to setupEpoch under the hood, this should ONLY be called as a view function, and not from within - * this contract. * @return The validator set for the current epoch */ function getCurrentEpochCommittee() external view override(ILeonidas) returns (address[] memory) { @@ -306,23 +303,23 @@ contract Leonidas is Ownable, ILeonidas { return address(0); } - Epoch storage epoch = epochs[epochNumber]; + // Epoch storage epoch = epochs[epochNumber]; - // If the epoch is setup, we can just return the proposer. Otherwise we have to emulate sampling - if (epoch.sampleSeed != 0) { - uint256 committeeSize = epoch.committee.length; - if (committeeSize == 0) { - return address(0); - } + // // If the epoch is setup, we can just return the proposer. Otherwise we have to emulate sampling + // if (epoch.sampleSeed != 0) { + // uint256 committeeSize = epoch.committee.length; + // if (committeeSize == 0) { + // return address(0); + // } - return - epoch.committee[_computeProposerIndex(epochNumber, slot, epoch.sampleSeed, committeeSize)]; - } + // return + // epoch.committee[_computeProposerIndex(epochNumber, slot, epoch.sampleSeed, committeeSize)]; + // } - // Allow anyone if there is no validator set - if (validatorSet.length() == 0) { - return address(0); - } + // // Allow anyone if there is no validator set + // if (validatorSet.length() == 0) { + // return address(0); + // } // Emulate a sampling of the validators uint256 sampleSeed = _getSampleSeed(epochNumber); diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index b8c8af4079d..03131e96103 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -28,6 +28,8 @@ import {IFeeJuicePortal} from "../../src/core/interfaces/IFeeJuicePortal.sol"; * We will skip these test if we are running with IS_DEV_NET = true */ +import "forge-std/console.sol"; + contract SpartaTest is DecoderBase { using MessageHashUtils for bytes32; @@ -275,6 +277,34 @@ contract SpartaTest is DecoderBase { assertEq(rollup.archive(), archive, "Invalid archive"); } + + // We need to make sure that the get committee function is actually + // working the way we expect it to + // This is blowing up the test that we want to test + function testGetCommitteeAtNonSetupEpoch() public setup(4) { + if (Constants.IS_DEV_NET == 1) { + return; + } + + uint256 _epochsToJump = 1; + uint256 pre = rollup.getCurrentEpoch(); + vm.warp( + block.timestamp + uint256(_epochsToJump) * rollup.EPOCH_DURATION() * rollup.SLOT_DURATION() + ); + uint256 post = rollup.getCurrentEpoch(); + assertEq(pre + _epochsToJump, post, "Invalid epoch"); + + // Test that the committee returned from getCommitteeAt is the same as the one returned from getCurrentEpochCommittee + address[] memory committeeAtNow = rollup.getCommitteeAt(block.timestamp); + address[] memory currentCommittee = rollup.getCurrentEpochCommittee(); + assertEq(currentCommittee.length, 4, "Committee should be empty"); + assertEq(committeeAtNow.length, currentCommittee.length, "Committee now and get committee should be the same length"); + + for (uint256 i = 0; i < currentCommittee.length; i++) { + assertEq(currentCommittee[i], committeeAtNow[i], "Committee now and get committee should be the same length"); + } + } + function _populateInbox(address _sender, bytes32 _recipient, bytes32[] memory _contents) internal { for (uint256 i = 0; i < _contents.length; i++) { vm.prank(_sender); diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index ad494f2668f..c17b92bce54 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -1,7 +1,7 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; import { type AztecNodeConfig, type AztecNodeService } from '@aztec/aztec-node'; -import { CompleteAddress, type DebugLogger, Fr, GrumpkinScalar, type SentTx, TxStatus, sleep } from '@aztec/aztec.js'; -import { EthAddress, IS_DEV_NET } from '@aztec/circuits.js'; +import { CheatCodes, CompleteAddress, type DebugLogger, Fr, GrumpkinScalar, type SentTx, TxStatus, sleep } from '@aztec/aztec.js'; +import { AZTEC_EPOCH_DURATION, AZTEC_SLOT_DURATION, EthAddress, IS_DEV_NET } from '@aztec/circuits.js'; import { type BootstrapNode } from '@aztec/p2p'; import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; @@ -32,6 +32,7 @@ describe('e2e_p2p_network', () => { let teardown: () => Promise; let bootstrapNode: BootstrapNode; let bootstrapNodeEnr: string; + let cheatCodes: CheatCodes; beforeEach(async () => { // If we want to test with interval mining, we can use the local host and start `anvil --block-time 12` @@ -57,7 +58,7 @@ describe('e2e_p2p_network', () => { initialValidators.push(EthAddress.fromString(account.address)); } - ({ teardown, config, logger } = await setup(0, { initialValidators, ...options })); + ({ teardown, config, logger, cheatCodes } = await setup(0, { initialValidators, ...options })); bootstrapNode = await createBootstrapNode(BOOT_NODE_UDP_PORT); bootstrapNodeEnr = bootstrapNode.getENR().encodeTxt(); @@ -74,6 +75,12 @@ describe('e2e_p2p_network', () => { } }); + const jumpIntoNextEpoch = async () => { + const currentTimestamp = await cheatCodes.eth.timestamp(); + const timeJump = currentTimestamp + (AZTEC_EPOCH_DURATION * AZTEC_SLOT_DURATION); + await cheatCodes.eth.warp(timeJump + 1); + }; + it.only('should rollup txs from all peers', async () => { // create the bootstrap node for the network if (!bootstrapNodeEnr) { @@ -93,8 +100,10 @@ describe('e2e_p2p_network', () => { /*activate validators=*/ !IS_DEV_NET, ); + // Warp an entire epoch ahead. So that the committee exists + await jumpIntoNextEpoch(); // wait a bit for peers to discover each other - await sleep(2000); + await sleep(4000); for (const node of nodes) { const context = await createPXEServiceAndSubmitTransactions(node, NUM_TXS_PER_NODE); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 3e3e94b2b1a..67152a5635a 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -88,6 +88,7 @@ import { getACVMConfig } from './get_acvm_config.js'; import { getBBConfig } from './get_bb_config.js'; import { isMetricsLoggingRequested, setupMetricsLogger } from './logging.js'; import { Watcher } from './watcher.js'; +import { ConsoleMessage } from 'puppeteer'; export { deployAndInitializeTokenAndBridgeContracts } from '../shared/cross_chain_test_harness.js'; @@ -149,6 +150,7 @@ export const setupL1Contracts = async ( }, }; + console.log("Initial validators", args.initialValidators); const l1Data = await deployL1Contracts(l1RpcUrl, account, chain, logger, l1Artifacts, { l2FeeJuiceAddress: FeeJuiceAddress, vkTreeRoot: getVKTreeRoot(), diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 2d9a5029351..c0b90f3ab01 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -37,7 +37,7 @@ export type EnvVar = | 'P2P_QUERY_FOR_IP' | 'P2P_TX_POOL_KEEP_PROVEN_FOR' | 'TELEMETRY' - | 'OTEL_SERVICE_NAME' + | 'OTEL_SERVICE_NAME' | 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT' | 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT' | 'NETWORK_NAME' @@ -105,6 +105,8 @@ export type EnvVar = | 'BOT_FLUSH_SETUP_TRANSACTIONS' | 'VALIDATOR_PRIVATE_KEY' | 'VALIDATOR_DISABLED' + | 'VALIDATOR_ATTESTATIONS_WAIT_TIMEOUT_MS' + | 'VALIDATOR_ATTESTATIONS_POOLING_INTERVAL_MS' | 'PROVER_NODE_DISABLE_AUTOMATIC_PROVING' | 'PROVER_NODE_MAX_PENDING_JOBS' | 'LOG_LEVEL' diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 6af0180251e..eeb7d2e5b14 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -263,6 +263,7 @@ export class P2PClient implements P2P { } public broadcastProposal(proposal: BlockProposal): void { + this.log.verbose(`Broadcasting proposal ${proposal.p2pMessageIdentifier()} to peers`); return this.p2pService.propagate(proposal); } diff --git a/yarn-project/p2p/src/service/libp2p_service.ts b/yarn-project/p2p/src/service/libp2p_service.ts index bc3a7c55594..bf3a9c1c144 100644 --- a/yarn-project/p2p/src/service/libp2p_service.ts +++ b/yarn-project/p2p/src/service/libp2p_service.ts @@ -316,7 +316,7 @@ export class LibP2PService implements P2PService { this.logger.verbose(`Sending message ${identifier} to peers`); const recipientsNum = await this.publishToTopic(parent.p2pTopic, message.toBuffer()); - this.logger.verbose(`Sent tx ${identifier} to ${recipientsNum} peers`); + this.logger.verbose(`Sent message ${identifier} to ${recipientsNum} peers`); } // Libp2p seems to hang sometimes if new peers are initiating connections. diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index aa1cb70b129..bf72924548c 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -90,6 +90,7 @@ export type L1SubmitProofArgs = { aggregationObject: Buffer; }; + export type MetadataForSlot = { proposer: EthAddress; slot: bigint; @@ -185,6 +186,7 @@ export class L1Publisher { return [slot, blockNumber]; } + public async validateBlockForSubmission( header: Header, digest: Buffer = new Fr(GENESIS_ARCHIVE_ROOT).toBuffer(), @@ -230,11 +232,6 @@ export class L1Publisher { this.rollupContract.read.archive(), ]); - console.log('metadata for the next eth block'); - console.table({ - slot, - pendingBlockNumber: pendingBlockCount - 1n, - }); return { proposer: EthAddress.fromString(submitter), slot, @@ -243,8 +240,28 @@ export class L1Publisher { }; } + + // /** + // * @notice Calls `getCommitteeAt` with the time of the next Ethereum block + // * @return committee - The committee at the next Ethereum block + // */ + // public async getCommitteeAtNextEthBlock(): Promise { + // // TODO(md): reuse as a helper? + // const lastBlockTimestamp = (await this.publicClient.getBlock()).timestamp; + // console.log('lastBlockTimestamp', lastBlockTimestamp); + // const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); + // console.log('ts', ts); + // const committee = await this.rollupContract.read.getCommitteeAt([ + // ts, + // ]); + // console.log('returned committee', committee); + // return committee.map(EthAddress.fromString); + // } + + public async getCurrentEpochCommittee(): Promise { const committee = await this.rollupContract.read.getCurrentEpochCommittee(); + console.log('returned committee', committee); return committee.map(EthAddress.fromString); } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 8e938fd4cb2..2b1658b77a9 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -477,8 +477,9 @@ export class Sequencer { const txHashes = validTxs.map(tx => tx.getTxHash()); this.isFlushing = false; - this.log.verbose('SEQUENCER | collectAttestations'); + this.log.verbose("Collecting attestations"); const attestations = await this.collectAttestations(block, txHashes); + this.log.verbose("Attestations collected"); try { await this.publishL2Block(block, attestations); @@ -514,16 +515,22 @@ export class Sequencer { // / \ // _____________/_ __ \_____________ - console.log('SEQUENCER | IS_DEV_NET', IS_DEV_NET); - console.log('SEQUENCER | this.validatorClient', this.validatorClient); if (IS_DEV_NET || !this.validatorClient) { + this.log.verbose("ATTEST | Skipping attestation collection"); return undefined; } + // const committeeAtNext = await this.publisher.getCommitteeAtNextEthBlock(); + // this.log.verbose(`ATTEST | committee at the next eth block length ${committeeAtNext.length}`); + + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962): inefficient to have a round trip in here - this should be cached const committee = await this.publisher.getCurrentEpochCommittee(); + this.log.verbose(`ATTEST | committee length ${committee.length}`); if (committee.length === 0) { + this.log.verbose(`ATTEST | committee length is 0, skipping`); + throw new Error('Committee length is 0, WHAT THE FUCK'); return undefined; } @@ -532,13 +539,23 @@ export class Sequencer { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7974): we do not have transaction[] lists in the block for now // Dont do anything with the proposals for now - just collect them + this.log.verbose("ATTEST | Creating block proposal"); const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txHashes); this.state = SequencerState.PUBLISHING_BLOCK_TO_PEERS; + this.log.verbose("Broadcasting block proposal to validators"); this.validatorClient.broadcastBlockProposal(proposal); + // Note do we know if it is wating for attestations as it thinks it should be + // proposing the block? + this.state = SequencerState.WAITING_FOR_ATTESTATIONS; const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations); + this.log.verbose("Collected attestations from validators"); + + // TODO: clean: SELF REPORT LMAO + const selfSign = await this.validatorClient.attestToProposal(proposal); + attestations.push(selfSign); // note: the smart contract requires that the signatures are provided in the order of the committee return await orderAttestations(attestations, committee); diff --git a/yarn-project/validator-client/src/config.ts b/yarn-project/validator-client/src/config.ts index 083beead6c1..65333c33961 100644 --- a/yarn-project/validator-client/src/config.ts +++ b/yarn-project/validator-client/src/config.ts @@ -1,5 +1,6 @@ +import { AZTEC_SLOT_DURATION } from '@aztec/circuits.js'; import { NULL_KEY } from '@aztec/ethereum'; -import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config'; +import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config'; /** * The Validator Configuration @@ -10,6 +11,12 @@ export interface ValidatorClientConfig { /** Do not run the validator */ disableValidator: boolean; + + /** Interval between polling for new attestations from peers */ + attestationPoolingIntervalMs: number; + + /** Wait for attestations timeout */ + attestationWaitTimeoutMs: number; } export const validatorClientConfigMappings: ConfigMappingsType = { @@ -23,6 +30,16 @@ export const validatorClientConfigMappings: ConfigMappingsType { + // Check that we have all of the proposal's transactions in our p2p client + const txHashes = proposal.txs; + const haveTx = txHashes.map(txHash => this.p2pClient.getTxStatus(txHash)); + + if (haveTx.length !== txHashes.length) { + console.log("WE ARE MISSING TRANSCTIONS"); + } + return this.validationService.attestToProposal(proposal); } @@ -82,18 +99,31 @@ export class ValidatorClient implements Validator { // Wait and poll the p2pClients attestation pool for this block // until we have enough attestations + const startTime = Date.now(); + const slot = proposal.header.globalVariables.slotNumber.toBigInt(); + // TODO: tidy + numberOfRequiredAttestations -= 1; // We self sign + this.log.info(`Waiting for ${numberOfRequiredAttestations} attestations for slot: ${slot}`); let attestations: BlockAttestation[] = [await this.attestToProposal(proposal)]; while (attestations.length < numberOfRequiredAttestations) { attestations = await this.p2pClient.getAttestationsForSlot(slot); + // Rememebr we can subtract 1 from this if we self sign if (attestations.length < numberOfRequiredAttestations) { + this.log.verbose(`SEAN: collected ${attestations.length} attestations so far ${numberOfRequiredAttestations} required`); this.log.verbose(`Waiting ${this.attestationPoolingIntervalMs}ms for more attestations...`); await sleep(this.attestationPoolingIntervalMs); } + + // FIX(md): kinna sad looking code + if (Date.now() - startTime > this.attestationWaitTimeoutMs) { + this.log.error(`Timeout waiting for ${numberOfRequiredAttestations} attestations for slot, ${slot}`); + throw new Error(`Timeout waiting for ${numberOfRequiredAttestations} attestations for slot, ${slot}`); + } } this.log.info(`Collected all attestations for slot, ${slot}`); From fc7a04a18972669fb1a479b1edc3c6f47042a48e Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 30 Aug 2024 18:36:54 +0000 Subject: [PATCH 06/26] temp --- l1-contracts/src/core/Rollup.sol | 25 +------------------ .../src/p2p/block_attestation.ts | 12 ++++++--- yarn-project/circuit-types/src/p2p/mocks.ts | 7 ++++-- .../end-to-end/src/e2e_p2p_network.test.ts | 4 +-- yarn-project/end-to-end/src/fixtures/utils.ts | 1 - .../p2p/src/attestation_pool/mocks.ts | 9 ++++--- .../src/publisher/l1-publisher.ts | 16 +++++++----- .../src/sequencer/sequencer.test.ts | 3 ++- .../src/sequencer/sequencer.ts | 6 ++++- .../src/duties/validation_service.ts | 3 +-- 10 files changed, 40 insertions(+), 46 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 32a409434da..6c1d7da2273 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -563,29 +563,6 @@ contract Rollup is Leonidas, IRollup, ITestRollup { ); } - /** - * @notice Validates the header for submission - * - * @param _header - The proposed block header - * @param _signatures - The signatures for the attestations - * @param _digest - The digest that signatures signed - * @param _currentTime - The time of execution - * @dev - This value is provided to allow for simple simulation of future - * @param _flags - Flags specific to the execution, whether certain checks should be skipped - */ - function _validateHeader( - HeaderLib.Header memory _header, - SignatureLib.Signature[] memory _signatures, - bytes32 _digest, - uint256 _currentTime, - DataStructures.ExecutionFlags memory _flags - ) internal view { - _validateHeaderForSubmissionBase(_header, _currentTime, _flags); - _validateHeaderForSubmissionSequencerSelection( - _header.globalVariables.slotNumber, _signatures, _digest, _currentTime, _flags - ); - } - /** * @notice Validate a header for submission to the pending chain (sequencer selection checks) * @@ -641,7 +618,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup { revert Errors.Rollup__InvalidEpoch(currentEpoch, epochNumber); } - _processPendingBlock(_slot, _signatures, _digest, _flags); + _proposePendingBlock(_slot, _signatures, _digest, _flags); } /** diff --git a/yarn-project/circuit-types/src/p2p/block_attestation.ts b/yarn-project/circuit-types/src/p2p/block_attestation.ts index fd38d691172..2b9a13be63c 100644 --- a/yarn-project/circuit-types/src/p2p/block_attestation.ts +++ b/yarn-project/circuit-types/src/p2p/block_attestation.ts @@ -8,6 +8,7 @@ import { recoverMessageAddress } from 'viem'; import { Gossipable } from './gossipable.js'; import { Signature } from './signature.js'; import { TopicType, createTopicString } from './topic_type.js'; +import { TxHash } from '../tx/tx_hash.js'; export class BlockAttestationHash extends Buffer32 { constructor(hash: Buffer) { @@ -31,6 +32,7 @@ export class BlockAttestation extends Gossipable { public readonly header: Header, // TODO(https://github.com/AztecProtocol/aztec-packages/pull/7727#discussion_r1713670830): temporary public readonly archive: Fr, + public readonly txHashes: TxHash[], /** The signature of the block attester */ public readonly signature: Signature, ) { @@ -53,8 +55,10 @@ export class BlockAttestation extends Gossipable { async getSender() { if (!this.sender) { // Recover the sender from the attestation + const payload = serializeToBuffer([this.archive, this.txHashes]); + const payload0x: `0x${string}` = `0x${payload.toString('hex')}`; const address = await recoverMessageAddress({ - message: { raw: this.p2pMessageIdentifier().to0xString() }, + message: { raw: payload0x }, signature: this.signature.to0xString(), }); // Cache the sender for later use @@ -65,15 +69,15 @@ export class BlockAttestation extends Gossipable { } toBuffer(): Buffer { - return serializeToBuffer([this.header, this.archive, this.signature]); + return serializeToBuffer([this.header, this.archive, this.txHashes.length, this.txHashes, this.signature]); } static fromBuffer(buf: Buffer | BufferReader): BlockAttestation { const reader = BufferReader.asReader(buf); - return new BlockAttestation(reader.readObject(Header), reader.readObject(Fr), reader.readObject(Signature)); + return new BlockAttestation(reader.readObject(Header), reader.readObject(Fr), reader.readArray(reader.readNumber(), TxHash), reader.readObject(Signature)); } static empty(): BlockAttestation { - return new BlockAttestation(Header.empty(), Fr.ZERO, Signature.empty()); + return new BlockAttestation(Header.empty(), Fr.ZERO, [], Signature.empty()); } } diff --git a/yarn-project/circuit-types/src/p2p/mocks.ts b/yarn-project/circuit-types/src/p2p/mocks.ts index f85ba76a6ae..a177774371e 100644 --- a/yarn-project/circuit-types/src/p2p/mocks.ts +++ b/yarn-project/circuit-types/src/p2p/mocks.ts @@ -8,6 +8,7 @@ import { TxHash } from '../tx/tx_hash.js'; import { BlockAttestation } from './block_attestation.js'; import { BlockProposal } from './block_proposal.js'; import { Signature } from './signature.js'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; export const makeBlockProposal = async (signer?: PrivateKeyAccount): Promise => { signer = signer || randomSigner(); @@ -26,9 +27,11 @@ export const makeBlockAttestation = async (signer?: PrivateKeyAccount): Promise< const blockHeader = makeHeader(1); const archive = Fr.random(); - const signature = Signature.from0xString(await signer.signMessage({ message: { raw: archive.toString() } })); + const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()); + const hash: `0x${string}` = `0x${serializeToBuffer([archive, txs]).toString('hex')}`; + const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } })); - return new BlockAttestation(blockHeader, archive, signature); + return new BlockAttestation(blockHeader, archive, txs, signature); }; export const randomSigner = (): PrivateKeyAccount => { diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index c17b92bce54..69098d1937c 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -36,7 +36,7 @@ describe('e2e_p2p_network', () => { beforeEach(async () => { // If we want to test with interval mining, we can use the local host and start `anvil --block-time 12` - const useLocalHost = true; + const useLocalHost = false; if (useLocalHost) { jest.setTimeout(300_000); } @@ -101,7 +101,7 @@ describe('e2e_p2p_network', () => { ); // Warp an entire epoch ahead. So that the committee exists - await jumpIntoNextEpoch(); + // await jumpIntoNextEpoch(); // wait a bit for peers to discover each other await sleep(4000); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 5f4496e9975..051e609f177 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -462,7 +462,6 @@ export async function setup( const wallets = numberOfAccounts > 0 ? await createAccounts(pxe, numberOfAccounts) : []; const cheatCodes = CheatCodes.create(config.l1RpcUrl, pxe!); - console.log('made account'); const teardown = async () => { if (aztecNode instanceof AztecNodeService) { diff --git a/yarn-project/p2p/src/attestation_pool/mocks.ts b/yarn-project/p2p/src/attestation_pool/mocks.ts index 22e5da70a94..00194d52b96 100644 --- a/yarn-project/p2p/src/attestation_pool/mocks.ts +++ b/yarn-project/p2p/src/attestation_pool/mocks.ts @@ -1,6 +1,7 @@ -import { BlockAttestation, Signature } from '@aztec/circuit-types'; +import { BlockAttestation, Signature, TxHash } from '@aztec/circuit-types'; import { makeHeader } from '@aztec/circuits.js/testing'; import { Fr } from '@aztec/foundation/fields'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type PrivateKeyAccount } from 'viem'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; @@ -25,9 +26,11 @@ export const mockAttestation = async (signer: PrivateKeyAccount, slot: number = // Use arbitrary numbers for all other than slot const header = makeHeader(1, 2, slot); const archive = Fr.random(); - const message = archive.toString(); + const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()); + + const message: `0x${string}` = `0x${serializeToBuffer([archive, txs]).toString('hex')}`; const sigString = await signer.signMessage({ message }); const signature = Signature.from0xString(sigString); - return new BlockAttestation(header, archive, signature); + return new BlockAttestation(header, archive, txs, signature); }; diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 6643c0d5a88..371194b4bb1 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,4 +1,4 @@ -import { type L2Block, type Signature } from '@aztec/circuit-types'; +import { TxHash, type L2Block, type Signature } from '@aztec/circuit-types'; import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; import { ETHEREUM_SLOT_DURATION, EthAddress, GENESIS_ARCHIVE_ROOT, type Header, type Proof } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; @@ -302,7 +302,7 @@ export class L1Publisher { return false; } - const processTxArgs = { + const proposeTxArgs = { header: block.header.toBuffer(), archive: block.archive.root.toBuffer(), blockHash: block.header.hash().toBuffer(), @@ -311,6 +311,8 @@ export class L1Publisher { txHashes: txHashes ?? [], // NTS(md): should be 32 bytes? }; + console.log('proposeTxArgs', proposeTxArgs); + // Publish body and propose block (if not already published) if (!this.interrupted) { let txHash; @@ -318,9 +320,9 @@ export class L1Publisher { if (await this.checkIfTxsAreAvailable(block)) { this.log.verbose(`Transaction effects of block ${block.number} already published.`, ctx); - txHash = await this.sendProposeWithoutBodyTx(processTxArgs); + txHash = await this.sendProposeWithoutBodyTx(proposeTxArgs); } else { - txHash = await this.sendProposeTx(processTxArgs); + txHash = await this.sendProposeTx(proposeTxArgs); } if (!txHash) { @@ -534,11 +536,13 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - if (!L1Publisher.SKIP_SIMULATION) { + console.log('args', args); + + // if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.propose(args, { account: this.account, }); - } + // } return await this.rollupContract.write.propose(args, { account: this.account, diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 24a52633326..2761a8323af 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -79,7 +79,8 @@ describe('sequencer', () => { return undefined; } - const attestation = new BlockAttestation(block.header, archive, mockedSig); + // TODO(md): might be errors in here + const attestation = new BlockAttestation(block.header, archive, [], mockedSig); (attestation as any).sender = committee[0]; return [attestation]; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 2b1658b77a9..60cee46ffa9 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -482,7 +482,7 @@ export class Sequencer { this.log.verbose("Attestations collected"); try { - await this.publishL2Block(block, attestations); + await this.publishL2Block(block, attestations, txHashes); this.metrics.recordPublishedBlock(workDuration); this.log.info( `Submitted rollup block ${block.number} with ${ @@ -557,6 +557,7 @@ export class Sequencer { const selfSign = await this.validatorClient.attestToProposal(proposal); attestations.push(selfSign); + // note: the smart contract requires that the signatures are provided in the order of the committee return await orderAttestations(attestations, committee); } @@ -572,6 +573,9 @@ export class Sequencer { // Publishes new block to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_BLOCK; + console.log('attestations', attestations); + console.log('txHashes', txHashes); + const publishedL2Block = await this.publisher.processL2Block(block, attestations, txHashes); if (publishedL2Block) { this.lastPublishedBlock = block.number; diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index da04ce8ac60..383544345ca 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -36,9 +36,8 @@ export class ValidationService { // TODO: in the function before this, check that all of the txns exist in the payload - console.log('attesting to proposal', proposal); const buf = proposal.getPayload(); const sig = await this.keyStore.sign(buf); - return new BlockAttestation(proposal.header, proposal.archive, sig); + return new BlockAttestation(proposal.header, proposal.archive, proposal.txs, sig); } } From 9eed29802926b2654801a9c804cc98218de773cc Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:38:08 +0000 Subject: [PATCH 07/26] temp --- l1-contracts/src/core/Rollup.sol | 3 ++- l1-contracts/src/core/interfaces/IRollup.sol | 4 +++- .../sequencer-client/src/publisher/l1-publisher.ts | 9 +++++---- yarn-project/sequencer-client/src/sequencer/sequencer.ts | 4 ++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 6c1d7da2273..a14459b7e49 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -199,7 +199,8 @@ contract Rollup is Leonidas, IRollup, ITestRollup { * @param _signatures - Signatures from the validators * @param _body - The body of the L2 block */ - function propose( + // Temp change name to fix viem issue + function proposeWithBody( bytes calldata _header, bytes32 _archive, bytes32 _blockHash, diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index d344202ce66..717b53952ae 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -38,7 +38,9 @@ interface IRollup { function OUTBOX() external view returns (IOutbox); - function propose( + // Temp: turns out there is a viem bug where it cannot differentiate between the two + // different types + function proposeWithBody( bytes calldata _header, bytes32 _archive, bytes32 _blockHash, diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 371194b4bb1..b553e381d4f 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -311,7 +311,7 @@ export class L1Publisher { txHashes: txHashes ?? [], // NTS(md): should be 32 bytes? }; - console.log('proposeTxArgs', proposeTxArgs); + // console.log('proposeTxArgs', proposeTxArgs); // Publish body and propose block (if not already published) if (!this.interrupted) { @@ -536,15 +536,16 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - console.log('args', args); + // console.log('args length', args.length); // if (!L1Publisher.SKIP_SIMULATION) { - await this.rollupContract.simulate.propose(args, { + const simulationResult = await this.rollupContract.simulate.proposeWithBody(args, { account: this.account, }); + console.log(simulationResult); // } - return await this.rollupContract.write.propose(args, { + return await this.rollupContract.write.proposeWithBody(args, { account: this.account, }); } else { diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 60cee46ffa9..b398824a5fc 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -573,8 +573,8 @@ export class Sequencer { // Publishes new block to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_BLOCK; - console.log('attestations', attestations); - console.log('txHashes', txHashes); + // console.log('attestations', attestations); + // console.log('txHashes', txHashes); const publishedL2Block = await this.publisher.processL2Block(block, attestations, txHashes); if (publishedL2Block) { From cc09455b58035356e63a343f0cfaabb41986b1b2 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Mon, 2 Sep 2024 17:30:40 +0000 Subject: [PATCH 08/26] temp --- yarn-project/end-to-end/src/fixtures/utils.ts | 1 + yarn-project/end-to-end/src/fixtures/watcher.ts | 8 ++++++++ .../sequencer-client/src/publisher/l1-publisher.ts | 12 ++++++++++++ .../sequencer-client/src/sequencer/sequencer.ts | 5 +++++ 4 files changed, 26 insertions(+) diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 051e609f177..d36464718fe 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -453,6 +453,7 @@ export async function setup( } } + // A watcher that performs time jumps in the sequencer when they are required const watcher = new Watcher( new EthCheatCodes(config.l1RpcUrl), deployL1ContractsValues.l1ContractAddresses.rollupAddress, diff --git a/yarn-project/end-to-end/src/fixtures/watcher.ts b/yarn-project/end-to-end/src/fixtures/watcher.ts index 0d254fbf5ff..b65b3010f9a 100644 --- a/yarn-project/end-to-end/src/fixtures/watcher.ts +++ b/yarn-project/end-to-end/src/fixtures/watcher.ts @@ -6,6 +6,13 @@ import { RollupAbi } from '@aztec/l1-artifacts'; import { type GetContractReturnType, type HttpTransport, type PublicClient, getAddress, getContract } from 'viem'; import type * as chains from 'viem/chains'; +/** + * Watcher + * + * The watcher is used within tests in order to adjust the timestamps of an automine chain to have the correct block.timestamp values + * that are expected with the pending chain's timeliness requirements. + * + */ export class Watcher { private rollup: GetContractReturnType>; @@ -55,6 +62,7 @@ export class Watcher { this.logger.error(`Failed to warp to timestamp ${timestamp}: ${e}`); } + console.log("The watcher has jumped slot") this.logger.info(`Slot ${currentSlot} was filled, jumped to next slot`); } } catch (err) { diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index b553e381d4f..15034abae41 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -12,6 +12,7 @@ import { type TelemetryClient } from '@aztec/telemetry-client'; import pick from 'lodash.pick'; import { + BaseError, ContractFunctionRevertedError, type GetContractReturnType, type Hex, @@ -567,6 +568,17 @@ export class L1Publisher { }); } } catch (err) { + // TODO: tidy up this error + if (err instanceof BaseError) { + const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); + if (revertError instanceof ContractFunctionRevertedError) { + // TODO: turn this into a function + const errorName = revertError.data?.errorName ?? ""; + const args = revertError.metaMessages && revertError.metaMessages?.length > 1 ? revertError.metaMessages[1].trimStart() : ''; + this.log.error(`propose failed with "${errorName}${args}"`) + return undefined; + } + } this.log.error(`Rollup publish failed`, err); return undefined; } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index b398824a5fc..9d971630b0f 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -216,7 +216,12 @@ export class Sequencer { let slot: bigint; try { slot = await this.mayProposeBlock(chainTipArchive, BigInt(newBlockNumber)); + // TODO(md) below in this block are for debugging remove + const seqEnr = this.p2pClient.getEnr(); + console.log("SEAN | ", seqEnr, " IS able to propose a block"); } catch (err) { + const seqEnr = this.p2pClient.getEnr(); + console.log("SEAN | ", seqEnr, " NOT able to propose a block"); this.log.debug(`Cannot propose for block ${newBlockNumber}`); return; } From 4727cd93c62d0916197ea6054fe35f13a7760402 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:28:51 +0000 Subject: [PATCH 09/26] temp: get passing with txhash payloads --- .../archiver/src/archiver/eth_log_handlers.ts | 8 +++++--- .../circuit-types/src/p2p/block_attestation.ts | 9 ++++++--- .../circuit-types/src/p2p/block_proposal.ts | 7 +++++-- .../global_variable_builder/global_builder.ts | 2 ++ .../src/publisher/l1-publisher.ts | 18 +++++++++++++----- .../src/sequencer/sequencer.ts | 15 +++++++++------ .../src/duties/validation_service.ts | 7 +++++-- 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/yarn-project/archiver/src/archiver/eth_log_handlers.ts b/yarn-project/archiver/src/archiver/eth_log_handlers.ts index 04d8a8b5339..5c8eefd64e5 100644 --- a/yarn-project/archiver/src/archiver/eth_log_handlers.ts +++ b/yarn-project/archiver/src/archiver/eth_log_handlers.ts @@ -110,7 +110,7 @@ async function getBlockMetadataFromRollupTx( data, }); - if (!(functionName === 'propose')) { + if (!(functionName === 'propose' || functionName === 'proposeWithBody')) { throw new Error(`Unexpected method called ${functionName}`); } const [headerHex, archiveRootHex, _] = args! as readonly [Hex, Hex, Hex]; @@ -152,10 +152,11 @@ async function getBlockBodiesFromAvailabilityOracleTx( // [ // "propose(bytes,bytes32,bytes32,(bool,uint8,bytes32,bytes32)[],bytes)": "08978fe9", // "propose(bytes,bytes32,bytes32,bytes)": "81e6f472", + // "proposeWithBody(bytes,bytes32,bytes32,bytes32[],(bool,uint8,bytes32,bytes32)[],bytes)": "b2283b07", // "publish(bytes calldata _body)" // ] - const DATA_INDEX = [4, 3, 0]; - const SUPPORTED_SIGS = ['0x08978fe9', '0x81e6f472', '0x7fd28346']; + const DATA_INDEX = [4, 3, 5, 0]; // index where the body is, in the parameters list + const SUPPORTED_SIGS = ['0x08978fe9', '0x81e6f472', '0xb2283b07', '0x7fd28346']; const signature = slice(data, 0, 4); @@ -163,6 +164,7 @@ async function getBlockBodiesFromAvailabilityOracleTx( throw new Error(`Unexpected method called ${signature}`); } + // Check if explicitly calling the DA oracle if (signature === SUPPORTED_SIGS[SUPPORTED_SIGS.length - 1]) { const { args } = decodeFunctionData({ abi: AvailabilityOracleAbi, diff --git a/yarn-project/circuit-types/src/p2p/block_attestation.ts b/yarn-project/circuit-types/src/p2p/block_attestation.ts index 2b9a13be63c..b98771f4a40 100644 --- a/yarn-project/circuit-types/src/p2p/block_attestation.ts +++ b/yarn-project/circuit-types/src/p2p/block_attestation.ts @@ -3,7 +3,7 @@ import { Buffer32 } from '@aztec/foundation/buffer'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { recoverMessageAddress } from 'viem'; +import { keccak256, recoverMessageAddress } from 'viem'; import { Gossipable } from './gossipable.js'; import { Signature } from './signature.js'; @@ -56,9 +56,12 @@ export class BlockAttestation extends Gossipable { if (!this.sender) { // Recover the sender from the attestation const payload = serializeToBuffer([this.archive, this.txHashes]); - const payload0x: `0x${string}` = `0x${payload.toString('hex')}`; + console.log("ATTESTATION PAYLOAD", payload); + // TODO(md) - temporarily hashing again to hav eless changes in the rollup + const hashed = keccak256(payload); + // const payload0x: `0x${string}` = `0x${payload.toString('hex')}`; const address = await recoverMessageAddress({ - message: { raw: payload0x }, + message: { raw: hashed }, signature: this.signature.to0xString(), }); // Cache the sender for later use diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.ts b/yarn-project/circuit-types/src/p2p/block_proposal.ts index 0d8c7514b08..3195a8c3f4c 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.ts @@ -3,7 +3,7 @@ import { Buffer32 } from '@aztec/foundation/buffer'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { recoverMessageAddress } from 'viem'; +import { keccak256, recoverMessageAddress } from 'viem'; import { TxHash } from '../tx/tx_hash.js'; import { Gossipable } from './gossipable.js'; @@ -57,8 +57,11 @@ export class BlockProposal extends Gossipable { async getSender() { if (!this.sender) { // performance note(): this signature method requires another hash behind the scenes + const hashed = keccak256(this.getPayload()); const address = await recoverMessageAddress({ - message: { raw: this.p2pMessageIdentifier().to0xString() }, + // TODO(md): fix this up + // message: { raw: this.p2pMessageIdentifier().to0xString() }, + message: { raw: hashed }, signature: this.signature.to0xString(), }); // Cache the sender for later use diff --git a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts index 91da4e1b46c..4904068fb11 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts @@ -69,7 +69,9 @@ export class GlobalVariableBuilder { slotNumber = await this.rollupContract.read.getSlotAt([ts]); } + // TODO: why does this work if I - 1 it const timestamp = await this.rollupContract.read.getTimestampForSlot([slotNumber]); + console.log("timestamp from the chain ", timestamp, " for the slot number ", slotNumber); const slotFr = new Fr(slotNumber); const timestampFr = new Fr(timestamp); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index c3f230d7a9d..81aa107fa96 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -32,6 +32,7 @@ import type * as chains from 'viem/chains'; import { type PublisherConfig, type TxSenderConfig } from './config.js'; import { L1PublisherMetrics } from './l1-publisher-metrics.js'; +import { keccak256 } from '@aztec/foundation/crypto'; /** * Stats for a sent transaction. @@ -298,6 +299,7 @@ export class L1Publisher { * @param block - L2 block to publish. * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise. */ + // TODO: rename propose public async processL2Block(block: L2Block, attestations?: Signature[], txHashes?: TxHash[]): Promise { const ctx = { blockNumber: block.number, @@ -305,7 +307,9 @@ export class L1Publisher { blockHash: block.hash().toString(), }; - const processTxArgs = { + // TODO: move this to take in the proposal to get the digest - rather than manually + const tempDigest = keccak256(serializeToBuffer(block.archive.root, txHashes ?? [])); + const proposeTxArgs = { header: block.header.toBuffer(), archive: block.archive.root.toBuffer(), blockHash: block.header.hash().toBuffer(), @@ -314,7 +318,7 @@ export class L1Publisher { txHashes: txHashes ?? [], // NTS(md): should be 32 bytes? }; - // console.log('proposeTxArgs', proposeTxArgs); + console.log('proposeTxArgs', proposeTxArgs); // Publish body and propose block (if not already published) if (!this.interrupted) { @@ -328,7 +332,8 @@ export class L1Publisher { // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which // make time consistency checks break. await this.validateBlockForSubmission(block.header, { - digest: block.archive.root.toBuffer(), + // digest: block.archive.root.toBuffer(), // THIS IS NOT THE DIGEST ANYMORE!!!!! + digest: tempDigest, signatures: attestations ?? [], }); @@ -552,12 +557,13 @@ export class L1Publisher { // console.log('args length', args.length); - // if (!L1Publisher.SKIP_SIMULATION) { + // We almost always want to skip simulation here if we are not already within the slot, else we will be one slot ahead + if (!L1Publisher.SKIP_SIMULATION) { const simulationResult = await this.rollupContract.simulate.proposeWithBody(args, { account: this.account, }); console.log(simulationResult); - // } + } return await this.rollupContract.write.proposeWithBody(args, { account: this.account, @@ -570,12 +576,14 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; + // We almost always want to skip simulation here if we are not already within the slot, else we will be one slot ahead if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.propose(args, { account: this.account, }); } + // TODO(md): first tx is failing in here return await this.rollupContract.write.propose(args, { account: this.account, }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 39e3bbc0ac0..906583826aa 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -244,6 +244,7 @@ export class Sequencer { this._feeRecipient, slot, ); + console.log("new global variables ", newGlobalVariables); // If I created a "partial" header here that should make our job much easier. const proposalHeader = new Header( @@ -512,14 +513,15 @@ export class Sequencer { this.isFlushing = true; } - protected async collectAttestations(block: L2Block): Promise { + protected async collectAttestations(block: L2Block, txHashes: TxHash[]): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962): inefficient to have a round trip in here - this should be cached const committee = await this.publisher.getCurrentEpochCommittee(); this.log.verbose(`ATTEST | committee length ${committee.length}`); if (committee.length === 0) { this.log.verbose(`ATTEST | committee length is 0, skipping`); - throw new Error('Committee length is 0, WHAT THE FUCK'); + // TODO(md): remove error + throw new Error('Committee length is 0, WHAT'); return undefined; } @@ -546,11 +548,12 @@ export class Sequencer { this.state = SequencerState.WAITING_FOR_ATTESTATIONS; const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations); - this.log.verbose("Collected attestations from validators"); + this.log.verbose(`Collected attestations from validators, number of attestations: ${attestations.length}`); - // TODO: clean: SELF REPORT LMAO - const selfSign = await this.validatorClient.attestToProposal(proposal); - attestations.push(selfSign); + // NOTE: is the self report now done in the method above + // // TODO: clean: SELF REPORT LMAO + // const selfSign = await this.validatorClient.attestToProposal(proposal); + // attestations.push(selfSign); // note: the smart contract requires that the signatures are provided in the order of the committee diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index 383544345ca..3d8577243e9 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -4,6 +4,7 @@ import { type Fr } from '@aztec/foundation/fields'; import { type ValidatorKeyStore } from '../key_store/interface.js'; import { serializeToBuffer } from '@aztec/foundation/serialize'; +import { keccak256 } from '@aztec/foundation/crypto'; export class ValidationService { constructor(private keyStore: ValidatorKeyStore) {} @@ -20,7 +21,9 @@ export class ValidationService { async createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { // Note: just signing the archive for now const payload = serializeToBuffer([archive, txs]); - const sig = await this.keyStore.sign(payload); + // TODO(temp hash it together before signing) + const hashed = keccak256(payload); + const sig = await this.keyStore.sign(hashed); return new BlockProposal(header, archive, txs, sig); } @@ -36,7 +39,7 @@ export class ValidationService { // TODO: in the function before this, check that all of the txns exist in the payload - const buf = proposal.getPayload(); + const buf = keccak256(proposal.getPayload()); const sig = await this.keyStore.sign(buf); return new BlockAttestation(proposal.header, proposal.archive, proposal.txs, sig); } From b4c2a46ed38dae792602befab19bffcc142c95e9 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:39:35 +0000 Subject: [PATCH 10/26] fix: make sure transactions are available in the tx pool --- .../src/p2p/block_attestation.ts | 3 +- .../end-to-end/src/e2e_p2p_network.test.ts | 92 +++++++++++++++---- yarn-project/p2p/src/client/p2p_client.ts | 27 +++++- .../p2p/src/service/reqresp/reqresp.ts | 5 + .../src/sequencer/sequencer.ts | 2 + .../validator-client/src/validator.ts | 50 ++++++++-- 6 files changed, 148 insertions(+), 31 deletions(-) diff --git a/yarn-project/circuit-types/src/p2p/block_attestation.ts b/yarn-project/circuit-types/src/p2p/block_attestation.ts index b98771f4a40..087da96fd15 100644 --- a/yarn-project/circuit-types/src/p2p/block_attestation.ts +++ b/yarn-project/circuit-types/src/p2p/block_attestation.ts @@ -56,8 +56,7 @@ export class BlockAttestation extends Gossipable { if (!this.sender) { // Recover the sender from the attestation const payload = serializeToBuffer([this.archive, this.txHashes]); - console.log("ATTESTATION PAYLOAD", payload); - // TODO(md) - temporarily hashing again to hav eless changes in the rollup + // TODO(md) - temporarily hashing again to have less changes in the rollup const hashed = keccak256(payload); // const payload0x: `0x${string}` = `0x${payload.toString('hex')}`; const address = await recoverMessageAddress({ diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 681846dba4b..306baccc8e1 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -84,6 +84,14 @@ describe('e2e_p2p_network', () => { await cheatCodes.warp(Number(timestamp)); }); + + const stopNodes = async (bootstrap: BootstrapNode, nodes: AztecNodeService[]) => { + for (const node of nodes) { + await node.stop(); + } + await bootstrap.stop(); + } + afterEach(() => teardown()); afterAll(() => { @@ -92,13 +100,7 @@ describe('e2e_p2p_network', () => { } }); - const jumpIntoNextEpoch = async () => { - const currentTimestamp = await cheatCodes.eth.timestamp(); - const timeJump = currentTimestamp + (AZTEC_EPOCH_DURATION * AZTEC_SLOT_DURATION); - await cheatCodes.eth.warp(timeJump + 1); - }; - - it.only('should rollup txs from all peers', async () => { + it('should rollup txs from all peers', async () => { // create the bootstrap node for the network if (!bootstrapNodeEnr) { throw new Error('Bootstrap node ENR is not available'); @@ -116,8 +118,6 @@ describe('e2e_p2p_network', () => { BOOT_NODE_UDP_PORT, ); - // Warp an entire epoch ahead. So that the committee exists - // await jumpIntoNextEpoch(); // wait a bit for peers to discover each other await sleep(4000); @@ -137,13 +137,71 @@ describe('e2e_p2p_network', () => { ); // shutdown all nodes. - for (const context of contexts) { - await context.node.stop(); - await context.pxeService.stop(); - } - await bootstrapNode.stop(); + await stopNodes(bootstrapNode, nodes); }); + it("should produce an attestation by requesting tx data over the p2p network", async () => { + + // Birds eye overview of the test + // We spin up x nodes + // We turn off receiving a tx via gossip from one of the nodes + // We send a transaction and gossip it to other nodes + // This node will receive an attestation that it does not have the data for + // It will request this data over the p2p layer + // We receive all of the attestations that we need and we produce the block + + if (!bootstrapNodeEnr) { + throw new Error('Bootstrap node ENR is not available'); + } + // create our network of nodes and submit txs into each of them + // the number of txs per node and the number of txs per rollup + // should be set so that the only way for rollups to be built + // is if the txs are successfully gossiped around the nodes. + const contexts: NodeContext[] = []; + const nodes: AztecNodeService[] = await createNodes( + config, + PEER_ID_PRIVATE_KEYS, + bootstrapNodeEnr, + NUM_NODES , + BOOT_NODE_UDP_PORT, + ); + + // wait a bit for peers to discover each other + await sleep(4000); + + console.log("\n\n\n\n\nALL NODES ARE CREATED\n\n\n\n\n"); + + // Replace the p2p node implementation of one of the nodes with a spy such that it does not store transactions that are gossiped to it + const nodeToTurnOff = 0; + jest.spyOn((nodes[nodeToTurnOff] as any).p2pClient.p2pService, 'processTxFromPeer') + .mockImplementation((args: any): Promise => { + console.log("mocked implementation of received transasction from peer", args.getTxHash()); + return Promise.resolve(); + }); + + // In this shuffle, the node that we turned off receipt through gossiping with will be the third to create a block + // And it will not produce a rollup as nothing exists within it's tx pool. + // So we only send transactions to the first two nodes + for (let i = 0; i < 2; i++) { + // The node which we disabled receiving from gossip from will not have any transactions in it's mempool + const context = await createPXEServiceAndSubmitTransactions(nodes[i], NUM_TXS_PER_NODE); + contexts.push(context); + } + + await Promise.all( + contexts.flatMap((context, i) => + context.txs.map(async (tx, j) => { + logger.info(`Waiting for tx ${i}-${j}: ${await tx.getTxHash()} to be mined`); + await tx.wait(); + logger.info(`Tx ${i}-${j}: ${await tx.getTxHash()} has been mined`); + return await tx.getTxHash(); + }), + ), + ); + + await stopNodes(bootstrapNode, nodes); + }) + it('should re-discover stored peers without bootstrap node', async () => { const contexts: NodeContext[] = []; const nodes: AztecNodeService[] = await createNodes( @@ -201,11 +259,7 @@ describe('e2e_p2p_network', () => { ); // shutdown all nodes. - // for (const context of contexts) { - for (const context of contexts) { - await context.node.stop(); - await context.pxeService.stop(); - } + await stopNodes(bootstrapNode, newNodes); }); // creates an instance of the PXE and submit a given number of transactions to it. diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 819c8e7eff8..9b2be9e194c 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -72,6 +72,13 @@ export interface P2P { // ^ This pattern is not my favorite (md) registerBlockProposalHandler(handler: (block: BlockProposal) => Promise): void; + /** + * Request a list of transactions from another peer by their tx hashes. + * @param txHashes - Hashes of the txs to query. + * @returns A list of transactions or undefined if the transactions are not found. + */ + requestTxs(txHashes: TxHash[]): Promise<(Tx | undefined)[]>; + /** * Request a transaction from another peer by its tx hash. * @param txHash - Hash of the tx to query. @@ -284,9 +291,25 @@ export class P2PClient implements P2P { this.p2pService.registerBlockReceivedCallback(handler); } - public requestTxByHash(txHash: TxHash): Promise { + // TODO: this will need a timeout + retry mechanism to make sure that we can retreive things on time + public requestTxs(txHashes: TxHash[]): Promise<(Tx | undefined)[]> { + // TODO: adjust this - what if one peer can service all of the requests? then we do not need to send all of these at once and overload the peer + // have a thinky + const requestPromises = txHashes.map(txHash => this.requestTxByHash(txHash)); + + return Promise.all(requestPromises); + } + + public async requestTxByHash(txHash: TxHash): Promise { // Underlying I want to use the libp2p service to just have a request method where the subprotocol is defined here - return this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash); + console.log("REQUESTING TX BY HASH via req resp!", txHash); + const tx = await this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash); + console.log("GOT TX FROM REQ RESP", tx); + if (tx) { + // tODO: do i need this await + await this.txPool.addTxs([tx]); + } + return tx; } /** diff --git a/yarn-project/p2p/src/service/reqresp/reqresp.ts b/yarn-project/p2p/src/service/reqresp/reqresp.ts index 2851c9e9fce..dada63424c2 100644 --- a/yarn-project/p2p/src/service/reqresp/reqresp.ts +++ b/yarn-project/p2p/src/service/reqresp/reqresp.ts @@ -96,8 +96,13 @@ export class ReqResp { ): Promise { try { const stream = await this.libp2p.dialProtocol(peerId, subProtocol); + this.logger.debug(`Stream opened with ${peerId.publicKey} for ${subProtocol}`); const result = await pipe([payload], stream, this.readMessage); + + await stream.close(); + this.logger.debug(`Stream closed with ${peerId.publicKey} for ${subProtocol}`); + return result; } catch (e) { this.logger.warn(`Failed to send request to peer ${peerId.publicKey}`); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 906583826aa..e6efaff427a 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -538,6 +538,7 @@ export class Sequencer { this.log.verbose("ATTEST | Creating block proposal"); const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txHashes); + console.log("PROPOSAL send form sequencer ", await proposal.getSender()); this.state = SequencerState.PUBLISHING_BLOCK_TO_PEERS; this.log.verbose("Broadcasting block proposal to validators"); @@ -576,6 +577,7 @@ export class Sequencer { const publishedL2Block = await this.publisher.processL2Block(block, attestations, txHashes); if (publishedL2Block) { + console.log("\n\n\n\nPUBLISHED L2 BLOCK", block.number, " with tx hashes ", txHashes); this.lastPublishedBlock = block.number; } else { throw new Error(`Failed to publish block ${block.number}`); diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index 5f926cf59ff..9aac5c2c362 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -64,23 +64,57 @@ export class ValidatorClient implements Validator { public registerBlockProposalHandler() { const handler = (block: BlockProposal): Promise => { - return this.validationService.attestToProposal(block); + return this.attestToProposal(block); }; this.p2pClient.registerBlockProposalHandler(handler); } async attestToProposal(proposal: BlockProposal): Promise { - // Check that we have all of the proposal's transactions in our p2p client - const txHashes = proposal.txs; - const haveTx = txHashes.map(txHash => this.p2pClient.getTxStatus(txHash)); - - if (haveTx.length !== txHashes.length) { - console.log("WE ARE MISSING TRANSCTIONS"); - } + // Check that all of the tranasctions in the proposal are available in the tx pool before attesting + await this.ensureTransactionsAreAvailable(proposal); + this.log.debug(`Transactions available, attesting to proposal with ${proposal.txs.length} transactions`); + // If the above function does not throw an error, then we can attest to the proposal return this.validationService.attestToProposal(proposal); } + /** + * Ensure that all of the transactions in the proposal are available in the tx pool before attesting + * + * 1. Check if the local tx pool contains all of the transactions in the proposal + * 2. If any transactions are not in the local tx pool, request them from the network + * 3. If we cannot retrieve them from the network, throw an error + * @param proposal - The proposal to attest to + */ + async ensureTransactionsAreAvailable(proposal: BlockProposal) { + const txHashes: TxHash[] = proposal.txs; + + const transactionStatuses = txHashes.map(txHash => this.p2pClient.getTxStatus(txHash)); + const haveAllTxs = transactionStatuses.every(tx => tx === 'pending' || tx === 'mined'); + + // Only in an if statement here for logging purposes + if (!haveAllTxs) { + const missingTxs: TxHash[] = txHashes.map((_, index) => { + if (!transactionStatuses[index]) { + return txHashes[index]; + } + return undefined; + }).filter(tx => tx !== undefined) as TxHash[]; + + this.log.verbose(`Missing ${missingTxs.length} attestations transactions in the tx pool, requesting from the network`); + + if (missingTxs) { + // If transactions are requested successfully, they will be written into the tx pool + const requestedTxs = await this.p2pClient.requestTxs(missingTxs); + const successfullyRetrievedMissingTxs = requestedTxs.every(tx => tx !== undefined); + if (!successfullyRetrievedMissingTxs) { + throw new Error("Failed to retrieve missing transactions"); + } + } + } + } + + createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { return this.validationService.createBlockProposal(header, archive, txs); } From 4a8d178d97f8af08ae157104450317bb91c2aaff Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 5 Sep 2024 17:40:20 +0000 Subject: [PATCH 11/26] chore: remove logs --- yarn-project/sequencer-client/src/sequencer/sequencer.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index e6efaff427a..67527602938 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -244,7 +244,6 @@ export class Sequencer { this._feeRecipient, slot, ); - console.log("new global variables ", newGlobalVariables); // If I created a "partial" header here that should make our job much easier. const proposalHeader = new Header( @@ -538,7 +537,6 @@ export class Sequencer { this.log.verbose("ATTEST | Creating block proposal"); const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txHashes); - console.log("PROPOSAL send form sequencer ", await proposal.getSender()); this.state = SequencerState.PUBLISHING_BLOCK_TO_PEERS; this.log.verbose("Broadcasting block proposal to validators"); @@ -572,12 +570,8 @@ export class Sequencer { // Publishes new block to the network and awaits the tx to be mined this.state = SequencerState.PUBLISHING_BLOCK; - // console.log('attestations', attestations); - // console.log('txHashes', txHashes); - const publishedL2Block = await this.publisher.processL2Block(block, attestations, txHashes); if (publishedL2Block) { - console.log("\n\n\n\nPUBLISHED L2 BLOCK", block.number, " with tx hashes ", txHashes); this.lastPublishedBlock = block.number; } else { throw new Error(`Failed to publish block ${block.number}`); From b4324fcf5513fba838c4f4322f0a082c2ab59796 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:15:19 +0000 Subject: [PATCH 12/26] fmt --- .../src/p2p/block_attestation.ts | 11 ++++-- .../circuit-types/src/p2p/block_proposal.ts | 4 +- yarn-project/circuit-types/src/p2p/mocks.ts | 2 +- .../end-to-end/src/e2e_p2p_network.test.ts | 37 +++++++++--------- yarn-project/end-to-end/src/fixtures/utils.ts | 1 - .../end-to-end/src/fixtures/watcher.ts | 1 - yarn-project/foundation/src/config/env_var.ts | 2 +- yarn-project/p2p/src/client/p2p_client.ts | 10 ++--- .../global_variable_builder/global_builder.ts | 2 - .../src/publisher/l1-publisher.ts | 39 ++++--------------- .../src/sequencer/sequencer.test.ts | 1 - .../src/sequencer/sequencer.ts | 11 +++--- yarn-project/validator-client/src/config.ts | 7 +++- .../src/duties/validation_service.ts | 4 +- .../validator-client/src/validator.ts | 33 +++++++++------- 15 files changed, 74 insertions(+), 91 deletions(-) diff --git a/yarn-project/circuit-types/src/p2p/block_attestation.ts b/yarn-project/circuit-types/src/p2p/block_attestation.ts index 087da96fd15..47ff33f90a7 100644 --- a/yarn-project/circuit-types/src/p2p/block_attestation.ts +++ b/yarn-project/circuit-types/src/p2p/block_attestation.ts @@ -5,10 +5,10 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { keccak256, recoverMessageAddress } from 'viem'; +import { TxHash } from '../tx/tx_hash.js'; import { Gossipable } from './gossipable.js'; import { Signature } from './signature.js'; import { TopicType, createTopicString } from './topic_type.js'; -import { TxHash } from '../tx/tx_hash.js'; export class BlockAttestationHash extends Buffer32 { constructor(hash: Buffer) { @@ -71,12 +71,17 @@ export class BlockAttestation extends Gossipable { } toBuffer(): Buffer { - return serializeToBuffer([this.header, this.archive, this.txHashes.length, this.txHashes, this.signature]); + return serializeToBuffer([this.header, this.archive, this.txHashes.length, this.txHashes, this.signature]); } static fromBuffer(buf: Buffer | BufferReader): BlockAttestation { const reader = BufferReader.asReader(buf); - return new BlockAttestation(reader.readObject(Header), reader.readObject(Fr), reader.readArray(reader.readNumber(), TxHash), reader.readObject(Signature)); + return new BlockAttestation( + reader.readObject(Header), + reader.readObject(Fr), + reader.readArray(reader.readNumber(), TxHash), + reader.readObject(Signature), + ); } static empty(): BlockAttestation { diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.ts b/yarn-project/circuit-types/src/p2p/block_proposal.ts index 3195a8c3f4c..1d74c70212c 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.ts @@ -36,17 +36,15 @@ export class BlockProposal extends Gossipable { /** The sequence of transactions in the block */ public readonly txs: TxHash[], /** The signer of the BlockProposal over the header of the new block*/ - public readonly signature: Signature + public readonly signature: Signature, ) { super(); } - static { this.p2pTopic = createTopicString(TopicType.block_proposal); } - override p2pMessageIdentifier(): Buffer32 { return BlockProposalHash.fromField(this.archive); } diff --git a/yarn-project/circuit-types/src/p2p/mocks.ts b/yarn-project/circuit-types/src/p2p/mocks.ts index a177774371e..f4646e20919 100644 --- a/yarn-project/circuit-types/src/p2p/mocks.ts +++ b/yarn-project/circuit-types/src/p2p/mocks.ts @@ -1,5 +1,6 @@ import { makeHeader } from '@aztec/circuits.js/testing'; import { Fr } from '@aztec/foundation/fields'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type PrivateKeyAccount } from 'viem'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; @@ -8,7 +9,6 @@ import { TxHash } from '../tx/tx_hash.js'; import { BlockAttestation } from './block_attestation.js'; import { BlockProposal } from './block_proposal.js'; import { Signature } from './signature.js'; -import { serializeToBuffer } from '@aztec/foundation/serialize'; export const makeBlockProposal = async (signer?: PrivateKeyAccount): Promise => { signer = signer || randomSigner(); diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 306baccc8e1..6958f102db2 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -1,12 +1,18 @@ import { getSchnorrAccount } from '@aztec/accounts/schnorr'; import { type AztecNodeConfig, type AztecNodeService } from '@aztec/aztec-node'; -import { CheatCodes, CompleteAddress, type DebugLogger, Fr, GrumpkinScalar, type SentTx, TxStatus, sleep, +import { + CompleteAddress, + type DebugLogger, type DeployL1Contracts, EthCheatCodes, + Fr, + GrumpkinScalar, + type SentTx, + TxStatus, + sleep, } from '@aztec/aztec.js'; -import { AZTEC_EPOCH_DURATION, AZTEC_SLOT_DURATION, EthAddress } from '@aztec/circuits.js'; -import { -} from '@aztec/aztec.js'; +import '@aztec/aztec.js'; +import { EthAddress } from '@aztec/circuits.js'; import { RollupAbi } from '@aztec/l1-artifacts'; import { type BootstrapNode } from '@aztec/p2p'; import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; @@ -39,7 +45,6 @@ describe('e2e_p2p_network', () => { let teardown: () => Promise; let bootstrapNode: BootstrapNode; let bootstrapNodeEnr: string; - let cheatCodes: CheatCodes; let deployL1ContractsValues: DeployL1Contracts; beforeEach(async () => { @@ -84,13 +89,12 @@ describe('e2e_p2p_network', () => { await cheatCodes.warp(Number(timestamp)); }); - const stopNodes = async (bootstrap: BootstrapNode, nodes: AztecNodeService[]) => { for (const node of nodes) { await node.stop(); } await bootstrap.stop(); - } + }; afterEach(() => teardown()); @@ -140,8 +144,7 @@ describe('e2e_p2p_network', () => { await stopNodes(bootstrapNode, nodes); }); - it("should produce an attestation by requesting tx data over the p2p network", async () => { - + it('should produce an attestation by requesting tx data over the p2p network', async () => { // Birds eye overview of the test // We spin up x nodes // We turn off receiving a tx via gossip from one of the nodes @@ -162,22 +165,20 @@ describe('e2e_p2p_network', () => { config, PEER_ID_PRIVATE_KEYS, bootstrapNodeEnr, - NUM_NODES , + NUM_NODES, BOOT_NODE_UDP_PORT, ); // wait a bit for peers to discover each other await sleep(4000); - console.log("\n\n\n\n\nALL NODES ARE CREATED\n\n\n\n\n"); - // Replace the p2p node implementation of one of the nodes with a spy such that it does not store transactions that are gossiped to it - const nodeToTurnOff = 0; - jest.spyOn((nodes[nodeToTurnOff] as any).p2pClient.p2pService, 'processTxFromPeer') - .mockImplementation((args: any): Promise => { - console.log("mocked implementation of received transasction from peer", args.getTxHash()); + const nodeToTurnOffTxGossip = 0; + jest + .spyOn((nodes[nodeToTurnOffTxGossip] as any).p2pClient.p2pService, 'processTxFromPeer') + .mockImplementation((): Promise => { return Promise.resolve(); - }); + }); // In this shuffle, the node that we turned off receipt through gossiping with will be the third to create a block // And it will not produce a rollup as nothing exists within it's tx pool. @@ -200,7 +201,7 @@ describe('e2e_p2p_network', () => { ); await stopNodes(bootstrapNode, nodes); - }) + }); it('should re-discover stored peers without bootstrap node', async () => { const contexts: NodeContext[] = []; diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index f64f29469b1..e8c37b0bd67 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -149,7 +149,6 @@ export const setupL1Contracts = async ( }, }; - console.log("Initial validators", args.initialValidators); const l1Data = await deployL1Contracts(l1RpcUrl, account, chain, logger, l1Artifacts, { l2FeeJuiceAddress: FeeJuiceAddress, vkTreeRoot: getVKTreeRoot(), diff --git a/yarn-project/end-to-end/src/fixtures/watcher.ts b/yarn-project/end-to-end/src/fixtures/watcher.ts index b65b3010f9a..0e332b9b941 100644 --- a/yarn-project/end-to-end/src/fixtures/watcher.ts +++ b/yarn-project/end-to-end/src/fixtures/watcher.ts @@ -62,7 +62,6 @@ export class Watcher { this.logger.error(`Failed to warp to timestamp ${timestamp}: ${e}`); } - console.log("The watcher has jumped slot") this.logger.info(`Slot ${currentSlot} was filled, jumped to next slot`); } } catch (err) { diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index c11a3fd0176..1dbdba68c45 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -38,7 +38,7 @@ export type EnvVar = | 'P2P_QUERY_FOR_IP' | 'P2P_TX_POOL_KEEP_PROVEN_FOR' | 'TELEMETRY' - | 'OTEL_SERVICE_NAME' + | 'OTEL_SERVICE_NAME' | 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT' | 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT' | 'NETWORK_NAME' diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 9b2be9e194c..a16f87b394d 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -296,19 +296,17 @@ export class P2PClient implements P2P { // TODO: adjust this - what if one peer can service all of the requests? then we do not need to send all of these at once and overload the peer // have a thinky const requestPromises = txHashes.map(txHash => this.requestTxByHash(txHash)); - return Promise.all(requestPromises); } public async requestTxByHash(txHash: TxHash): Promise { - // Underlying I want to use the libp2p service to just have a request method where the subprotocol is defined here - console.log("REQUESTING TX BY HASH via req resp!", txHash); - const tx = await this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash); - console.log("GOT TX FROM REQ RESP", tx); + const tx = await this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash); + + this.log.debug(`Requested ${txHash.toString()} from peer | success = ${!!tx}`); if (tx) { - // tODO: do i need this await await this.txPool.addTxs([tx]); } + return tx; } diff --git a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts index 4904068fb11..91da4e1b46c 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts @@ -69,9 +69,7 @@ export class GlobalVariableBuilder { slotNumber = await this.rollupContract.read.getSlotAt([ts]); } - // TODO: why does this work if I - 1 it const timestamp = await this.rollupContract.read.getTimestampForSlot([slotNumber]); - console.log("timestamp from the chain ", timestamp, " for the slot number ", slotNumber); const slotFr = new Fr(slotNumber); const timestampFr = new Fr(timestamp); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 81aa107fa96..4571e240737 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,7 +1,8 @@ -import { TxHash, type L2Block, type Signature } from '@aztec/circuit-types'; +import { type L2Block, type Signature, type TxHash } from '@aztec/circuit-types'; import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; import { ETHEREUM_SLOT_DURATION, EthAddress, type Header, type Proof } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; +import { keccak256 } from '@aztec/foundation/crypto'; import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { serializeToBuffer } from '@aztec/foundation/serialize'; @@ -32,7 +33,6 @@ import type * as chains from 'viem/chains'; import { type PublisherConfig, type TxSenderConfig } from './config.js'; import { L1PublisherMetrics } from './l1-publisher-metrics.js'; -import { keccak256 } from '@aztec/foundation/crypto'; /** * Stats for a sent transaction. @@ -92,7 +92,6 @@ export type L1SubmitProofArgs = { aggregationObject: Buffer; }; - export type MetadataForSlot = { proposer: EthAddress; slot: bigint; @@ -251,28 +250,8 @@ export class L1Publisher { }; } - - // /** - // * @notice Calls `getCommitteeAt` with the time of the next Ethereum block - // * @return committee - The committee at the next Ethereum block - // */ - // public async getCommitteeAtNextEthBlock(): Promise { - // // TODO(md): reuse as a helper? - // const lastBlockTimestamp = (await this.publicClient.getBlock()).timestamp; - // console.log('lastBlockTimestamp', lastBlockTimestamp); - // const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); - // console.log('ts', ts); - // const committee = await this.rollupContract.read.getCommitteeAt([ - // ts, - // ]); - // console.log('returned committee', committee); - // return committee.map(EthAddress.fromString); - // } - - public async getCurrentEpochCommittee(): Promise { const committee = await this.rollupContract.read.getCurrentEpochCommittee(); - console.log('returned committee', committee); return committee.map(EthAddress.fromString); } @@ -318,8 +297,6 @@ export class L1Publisher { txHashes: txHashes ?? [], // NTS(md): should be 32 bytes? }; - console.log('proposeTxArgs', proposeTxArgs); - // Publish body and propose block (if not already published) if (!this.interrupted) { let txHash; @@ -555,14 +532,11 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; - // console.log('args length', args.length); - // We almost always want to skip simulation here if we are not already within the slot, else we will be one slot ahead if (!L1Publisher.SKIP_SIMULATION) { const simulationResult = await this.rollupContract.simulate.proposeWithBody(args, { account: this.account, }); - console.log(simulationResult); } return await this.rollupContract.write.proposeWithBody(args, { @@ -594,9 +568,12 @@ export class L1Publisher { const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); if (revertError instanceof ContractFunctionRevertedError) { // TODO: turn this into a function - const errorName = revertError.data?.errorName ?? ""; - const args = revertError.metaMessages && revertError.metaMessages?.length > 1 ? revertError.metaMessages[1].trimStart() : ''; - this.log.error(`propose failed with "${errorName}${args}"`) + const errorName = revertError.data?.errorName ?? ''; + const args = + revertError.metaMessages && revertError.metaMessages?.length > 1 + ? revertError.metaMessages[1].trimStart() + : ''; + this.log.error(`propose failed with "${errorName}${args}"`); return undefined; } } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index b15c53b7cf7..e4c65545d12 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -74,7 +74,6 @@ describe('sequencer', () => { const committee = [EthAddress.random()]; const getSignatures = () => [mockedSig]; const getAttestations = () => { - // TODO(md): might be errors in here const attestation = new BlockAttestation(block.header, archive, [], mockedSig); (attestation as any).sender = committee[0]; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 67527602938..435ea0d2b3c 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -6,7 +6,7 @@ import { type ProcessedTx, Signature, Tx, - TxHash, + type TxHash, type TxValidator, } from '@aztec/circuit-types'; import { type AllowedElement, BlockProofError, PROVING_STATUS } from '@aztec/circuit-types/interfaces'; @@ -489,9 +489,9 @@ export class Sequencer { const txHashes = validTxs.map(tx => tx.getTxHash()); this.isFlushing = false; - this.log.verbose("Collecting attestations"); + this.log.verbose('Collecting attestations'); const attestations = await this.collectAttestations(block, txHashes); - this.log.verbose("Attestations collected"); + this.log.verbose('Attestations collected'); try { await this.publishL2Block(block, attestations, txHashes); @@ -535,11 +535,11 @@ export class Sequencer { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7974): we do not have transaction[] lists in the block for now // Dont do anything with the proposals for now - just collect them - this.log.verbose("ATTEST | Creating block proposal"); + this.log.verbose('ATTEST | Creating block proposal'); const proposal = await this.validatorClient.createBlockProposal(block.header, block.archive.root, txHashes); this.state = SequencerState.PUBLISHING_BLOCK_TO_PEERS; - this.log.verbose("Broadcasting block proposal to validators"); + this.log.verbose('Broadcasting block proposal to validators'); this.validatorClient.broadcastBlockProposal(proposal); // Note do we know if it is wating for attestations as it thinks it should be @@ -554,7 +554,6 @@ export class Sequencer { // const selfSign = await this.validatorClient.attestToProposal(proposal); // attestations.push(selfSign); - // note: the smart contract requires that the signatures are provided in the order of the committee return await orderAttestations(attestations, committee); } diff --git a/yarn-project/validator-client/src/config.ts b/yarn-project/validator-client/src/config.ts index 65333c33961..241bffbfda1 100644 --- a/yarn-project/validator-client/src/config.ts +++ b/yarn-project/validator-client/src/config.ts @@ -1,6 +1,11 @@ import { AZTEC_SLOT_DURATION } from '@aztec/circuits.js'; import { NULL_KEY } from '@aztec/ethereum'; -import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config'; +import { + type ConfigMappingsType, + booleanConfigHelper, + getConfigFromMappings, + numberConfigHelper, +} from '@aztec/foundation/config'; /** * The Validator Configuration diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index 3d8577243e9..6da7e816b76 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -1,10 +1,10 @@ import { BlockAttestation, BlockProposal, type TxHash } from '@aztec/circuit-types'; import { type Header } from '@aztec/circuits.js'; +import { keccak256 } from '@aztec/foundation/crypto'; import { type Fr } from '@aztec/foundation/fields'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type ValidatorKeyStore } from '../key_store/interface.js'; -import { serializeToBuffer } from '@aztec/foundation/serialize'; -import { keccak256 } from '@aztec/foundation/crypto'; export class ValidationService { constructor(private keyStore: ValidatorKeyStore) {} diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index 9aac5c2c362..79df6c7e25a 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -26,7 +26,6 @@ export interface Validator { /** Validator Client */ export class ValidatorClient implements Validator { - private validationService: ValidationService; constructor( @@ -34,7 +33,8 @@ export class ValidatorClient implements Validator { private p2pClient: P2P, private attestationPoolingIntervalMs: number, private attestationWaitTimeoutMs: number, - private log = createDebugLogger('aztec:validator')) { + private log = createDebugLogger('aztec:validator'), + ) { //TODO: We need to setup and store all of the currently active validators https://github.com/AztecProtocol/aztec-packages/issues/7962 this.validationService = new ValidationService(keyStore); @@ -48,7 +48,7 @@ export class ValidatorClient implements Validator { localKeyStore, p2pClient, config.attestationPoolingIntervalMs, - config.attestationWaitTimeoutMs + config.attestationWaitTimeoutMs, ); validator.registerBlockProposalHandler(); return validator; @@ -94,27 +94,30 @@ export class ValidatorClient implements Validator { // Only in an if statement here for logging purposes if (!haveAllTxs) { - const missingTxs: TxHash[] = txHashes.map((_, index) => { - if (!transactionStatuses[index]) { - return txHashes[index]; - } - return undefined; - }).filter(tx => tx !== undefined) as TxHash[]; - - this.log.verbose(`Missing ${missingTxs.length} attestations transactions in the tx pool, requesting from the network`); + const missingTxs: TxHash[] = txHashes + .map((_, index) => { + if (!transactionStatuses[index]) { + return txHashes[index]; + } + return undefined; + }) + .filter(tx => tx !== undefined) as TxHash[]; + + this.log.verbose( + `Missing ${missingTxs.length} attestations transactions in the tx pool, requesting from the network`, + ); if (missingTxs) { // If transactions are requested successfully, they will be written into the tx pool const requestedTxs = await this.p2pClient.requestTxs(missingTxs); const successfullyRetrievedMissingTxs = requestedTxs.every(tx => tx !== undefined); if (!successfullyRetrievedMissingTxs) { - throw new Error("Failed to retrieve missing transactions"); + throw new Error('Failed to retrieve missing transactions'); } } } } - createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { return this.validationService.createBlockProposal(header, archive, txs); } @@ -150,7 +153,9 @@ export class ValidatorClient implements Validator { // Rememebr we can subtract 1 from this if we self sign if (attestations.length < numberOfRequiredAttestations) { - this.log.verbose(`SEAN: collected ${attestations.length} attestations so far ${numberOfRequiredAttestations} required`); + this.log.verbose( + `SEAN: collected ${attestations.length} attestations so far ${numberOfRequiredAttestations} required`, + ); this.log.verbose(`Waiting ${this.attestationPoolingIntervalMs}ms for more attestations...`); await sleep(this.attestationPoolingIntervalMs); } From a803a94457d78782475fe3ad2cdbefd8d347a984 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:50:05 +0000 Subject: [PATCH 13/26] =?UTF-8?q?=F0=9F=AA=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/core/sequencer_selection/Leonidas.sol | 30 +++++++------- l1-contracts/test/sparta/Sparta.t.sol | 39 +++---------------- .../end-to-end/src/e2e_p2p_network.test.ts | 34 +++++++++------- yarn-project/p2p/src/client/p2p_client.ts | 2 - .../src/publisher/l1-publisher.ts | 6 +-- .../src/sequencer/sequencer.test.ts | 1 - .../src/sequencer/sequencer.ts | 14 +------ .../validator-client/src/validator.ts | 5 --- 8 files changed, 44 insertions(+), 87 deletions(-) diff --git a/l1-contracts/src/core/sequencer_selection/Leonidas.sol b/l1-contracts/src/core/sequencer_selection/Leonidas.sol index 1a7d3200a27..ad9550c794f 100644 --- a/l1-contracts/src/core/sequencer_selection/Leonidas.sol +++ b/l1-contracts/src/core/sequencer_selection/Leonidas.sol @@ -128,7 +128,7 @@ contract Leonidas is Ownable, ILeonidas { return epochs[_epoch].committee; } - function getCommitteeAt(uint256 _ts) public view returns (address[] memory) { + function getCommitteeAt(uint256 _ts) internal view returns (address[] memory) { uint256 epochNumber = getEpochAt(_ts); Epoch storage epoch = epochs[epochNumber]; @@ -293,23 +293,23 @@ contract Leonidas is Ownable, ILeonidas { return address(0); } - // Epoch storage epoch = epochs[epochNumber]; + Epoch storage epoch = epochs[epochNumber]; - // // If the epoch is setup, we can just return the proposer. Otherwise we have to emulate sampling - // if (epoch.sampleSeed != 0) { - // uint256 committeeSize = epoch.committee.length; - // if (committeeSize == 0) { - // return address(0); - // } + // If the epoch is setup, we can just return the proposer. Otherwise we have to emulate sampling + if (epoch.sampleSeed != 0) { + uint256 committeeSize = epoch.committee.length; + if (committeeSize == 0) { + return address(0); + } - // return - // epoch.committee[_computeProposerIndex(epochNumber, slot, epoch.sampleSeed, committeeSize)]; - // } + return + epoch.committee[_computeProposerIndex(epochNumber, slot, epoch.sampleSeed, committeeSize)]; + } - // // Allow anyone if there is no validator set - // if (validatorSet.length() == 0) { - // return address(0); - // } + // Allow anyone if there is no validator set + if (validatorSet.length() == 0) { + return address(0); + } // Emulate a sampling of the validators uint256 sampleSeed = _getSampleSeed(epochNumber); diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index a915b3996c8..a6f802dc102 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -26,8 +26,6 @@ import {IFeeJuicePortal} from "../../src/core/interfaces/IFeeJuicePortal.sol"; * The tests in this file is testing the sequencer selection */ -import "forge-std/console.sol"; - contract SpartaTest is DecoderBase { using MessageHashUtils for bytes32; @@ -186,14 +184,18 @@ contract SpartaTest is DecoderBase { rollup.setupEpoch(); + // TODO: include these in the base block and include in the load function + bytes32[] memory txHashes = new bytes32[](0); + if (_signatureCount > 0 && ree.proposer != address(0)) { address[] memory validators = rollup.getEpochCommittee(rollup.getCurrentEpoch()); ree.needed = validators.length * 2 / 3 + 1; SignatureLib.Signature[] memory signatures = new SignatureLib.Signature[](_signatureCount); + bytes32 digest = keccak256(abi.encodePacked(archive, txHashes)); for (uint256 i = 0; i < _signatureCount; i++) { - signatures[i] = createSignature(validators[i], archive); + signatures[i] = createSignature(validators[i], digest); } if (_expectRevert) { @@ -222,9 +224,6 @@ contract SpartaTest is DecoderBase { ree.shouldRevert = true; } - // TODO(md): this is temp and probably will not pass - bytes32[] memory txHashes = new bytes32[](0); - vm.prank(ree.proposer); rollup.propose(header, archive, bytes32(0), txHashes, signatures); @@ -278,34 +277,6 @@ contract SpartaTest is DecoderBase { assertEq(rollup.archive(), archive, "Invalid archive"); } - - // We need to make sure that the get committee function is actually - // working the way we expect it to - // This is blowing up the test that we want to test - function testGetCommitteeAtNonSetupEpoch() public setup(4) { - if (Constants.IS_DEV_NET == 1) { - return; - } - - uint256 _epochsToJump = 1; - uint256 pre = rollup.getCurrentEpoch(); - vm.warp( - block.timestamp + uint256(_epochsToJump) * rollup.EPOCH_DURATION() * rollup.SLOT_DURATION() - ); - uint256 post = rollup.getCurrentEpoch(); - assertEq(pre + _epochsToJump, post, "Invalid epoch"); - - // Test that the committee returned from getCommitteeAt is the same as the one returned from getCurrentEpochCommittee - address[] memory committeeAtNow = rollup.getCommitteeAt(block.timestamp); - address[] memory currentCommittee = rollup.getCurrentEpochCommittee(); - assertEq(currentCommittee.length, 4, "Committee should be empty"); - assertEq(committeeAtNow.length, currentCommittee.length, "Committee now and get committee should be the same length"); - - for (uint256 i = 0; i < currentCommittee.length; i++) { - assertEq(currentCommittee[i], committeeAtNow[i], "Committee now and get committee should be the same length"); - } - } - function _populateInbox(address _sender, bytes32 _recipient, bytes32[] memory _contents) internal { for (uint256 i = 0; i < _contents.length; i++) { vm.prank(_sender); diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 3f9908d9a64..512538585b1 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -164,22 +164,27 @@ describe('e2e_p2p_network', () => { await stopNodes(bootstrapNode, nodes); }); + // NOTE: If this test fails in a PR where the shuffling algorithm is changed, then it is failing as the node with + // the mocked p2p layer is being picked as the sequencer, and it does not have any transactions in it's mempool. + // If this is the case, then we should update the test to switch off the mempool of a different node. + // adjust `nodeToTurnOffTxGossip` in the test below. it('should produce an attestation by requesting tx data over the p2p network', async () => { - // Birds eye overview of the test - // We spin up x nodes - // We turn off receiving a tx via gossip from one of the nodes - // We send a transaction and gossip it to other nodes - // This node will receive an attestation that it does not have the data for - // It will request this data over the p2p layer - // We receive all of the attestations that we need and we produce the block + /** + * Birds eye overview of the test + * 1. We spin up x nodes + * 2. We turn off receiving a tx via gossip from one of the nodes + * 3. We send a transaction and gossip it to other nodes + * 4. This node will receive an attestation that it does not have the data for + * 5. It will request this data over the p2p layer + * 6. We receive all of the attestations that we need and we produce the block + * + * Note: we do not attempt to let this node produce a block, as it will not have received any transactions + * from the other pxes. + */ if (!bootstrapNodeEnr) { throw new Error('Bootstrap node ENR is not available'); } - // create our network of nodes and submit txs into each of them - // the number of txs per node and the number of txs per rollup - // should be set so that the only way for rollups to be built - // is if the txs are successfully gossiped around the nodes. const contexts: NodeContext[] = []; const nodes: AztecNodeService[] = await createNodes( config, @@ -193,6 +198,7 @@ describe('e2e_p2p_network', () => { await sleep(4000); // Replace the p2p node implementation of one of the nodes with a spy such that it does not store transactions that are gossiped to it + // Original implementation of `processTxFromPeer` will store received transactions in the tx pool. const nodeToTurnOffTxGossip = 0; jest .spyOn((nodes[nodeToTurnOffTxGossip] as any).p2pClient.p2pService, 'processTxFromPeer') @@ -200,11 +206,9 @@ describe('e2e_p2p_network', () => { return Promise.resolve(); }); - // In this shuffle, the node that we turned off receipt through gossiping with will be the third to create a block - // And it will not produce a rollup as nothing exists within it's tx pool. - // So we only send transactions to the first two nodes + // Only submit transactions to the first two nodes, so that we avoid our sequencer with a mocked p2p layer being picked to produce a block. + // If the shuffling algorithm changes, then this will need to be updated. for (let i = 0; i < 2; i++) { - // The node which we disabled receiving from gossip from will not have any transactions in it's mempool const context = await createPXEServiceAndSubmitTransactions(nodes[i], NUM_TXS_PER_NODE); contexts.push(context); } diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index a16f87b394d..4b079c9d5b3 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -293,8 +293,6 @@ export class P2PClient implements P2P { // TODO: this will need a timeout + retry mechanism to make sure that we can retreive things on time public requestTxs(txHashes: TxHash[]): Promise<(Tx | undefined)[]> { - // TODO: adjust this - what if one peer can service all of the requests? then we do not need to send all of these at once and overload the peer - // have a thinky const requestPromises = txHashes.map(txHash => this.requestTxByHash(txHash)); return Promise.all(requestPromises); } diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 8fbb6cb7445..d1a59a138af 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -264,7 +264,7 @@ export class L1Publisher { blockHash: block.header.hash().toBuffer(), body: block.body.toBuffer(), attestations, - txHashes: txHashes ?? [], // NTS(md): should be 32 bytes? + txHashes: txHashes ?? [], }; // Publish body and propose block (if not already published) @@ -503,6 +503,7 @@ export class L1Publisher { ] as const; // We almost always want to skip simulation here if we are not already within the slot, else we will be one slot ahead + // See comment attached to static SKIP_SIMULATION definition if (!L1Publisher.SKIP_SIMULATION) { const simulationResult = await this.rollupContract.simulate.proposeWithBody(args, { account: this.account, @@ -521,19 +522,18 @@ export class L1Publisher { ] as const; // We almost always want to skip simulation here if we are not already within the slot, else we will be one slot ahead + // See comment attached to static SKIP_SIMULATION definition if (!L1Publisher.SKIP_SIMULATION) { await this.rollupContract.simulate.propose(args, { account: this.account, }); } - // TODO(md): first tx is failing in here return await this.rollupContract.write.propose(args, { account: this.account, }); } } catch (err) { - // TODO: tidy up this error if (err instanceof BaseError) { const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); if (revertError instanceof ContractFunctionRevertedError) { diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 4afc7a35a64..73b441a58eb 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -75,7 +75,6 @@ describe('sequencer', () => { const committee = [EthAddress.random()]; const getSignatures = () => [mockedSig]; const getAttestations = () => { - // TODO(md): might be errors in here const attestation = new BlockAttestation(block.header, archive, [], mockedSig); (attestation as any).sender = committee[0]; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 77779a1166a..f57720ea370 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -520,12 +520,10 @@ export class Sequencer { protected async collectAttestations(block: L2Block, txHashes: TxHash[]): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962): inefficient to have a round trip in here - this should be cached const committee = await this.publisher.getCurrentEpochCommittee(); - this.log.verbose(`ATTEST | committee length ${committee.length}`); + this.log.debug(`Attesting committee length ${committee.length}`); if (committee.length === 0) { - this.log.verbose(`ATTEST | committee length is 0, skipping`); - // TODO(md): remove error - throw new Error('Committee length is 0, WHAT'); + this.log.debug(`Attesting committee length is 0, skipping`); return undefined; } @@ -547,18 +545,10 @@ export class Sequencer { this.log.verbose('Broadcasting block proposal to validators'); this.validatorClient.broadcastBlockProposal(proposal); - // Note do we know if it is wating for attestations as it thinks it should be - // proposing the block? - this.state = SequencerState.WAITING_FOR_ATTESTATIONS; const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations); this.log.verbose(`Collected attestations from validators, number of attestations: ${attestations.length}`); - // NOTE: is the self report now done in the method above - // // TODO: clean: SELF REPORT LMAO - // const selfSign = await this.validatorClient.attestToProposal(proposal); - // attestations.push(selfSign); - // note: the smart contract requires that the signatures are provided in the order of the committee return await orderAttestations(attestations, committee); } diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index 79df6c7e25a..838654160ca 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -126,9 +126,7 @@ export class ValidatorClient implements Validator { this.p2pClient.broadcastProposal(proposal); } - // Target is temporarily hardcoded, for a test, but will be calculated from smart contract // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962) - // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7976): require suitable timeouts async collectAttestations( proposal: BlockProposal, numberOfRequiredAttestations: number, @@ -140,9 +138,6 @@ export class ValidatorClient implements Validator { const slot = proposal.header.globalVariables.slotNumber.toBigInt(); - // TODO: tidy - numberOfRequiredAttestations -= 1; // We self sign - this.log.info(`Waiting for ${numberOfRequiredAttestations} attestations for slot: ${slot}`); const myAttestation = await this.attestToProposal(proposal); From 164c117e396d83fa4210db2a0715555fa0395416 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 6 Sep 2024 15:36:00 +0000 Subject: [PATCH 14/26] chore: validator tests --- .../end-to-end/src/e2e_p2p_network.test.ts | 25 ++++--- yarn-project/p2p/src/errors/index.ts | 1 + yarn-project/p2p/src/errors/reqresp.error.ts | 14 ++++ .../p2p/src/service/reqresp/interface.ts | 6 +- yarn-project/validator-client/package.json | 1 + .../validator-client/src/errors/index.ts | 1 + .../src/errors/validator.error.ts | 19 +++++ .../validator-client/src/validator.test.ts | 71 ++++++++++++++++++ .../validator-client/src/validator.ts | 75 +++++++------------ yarn-project/yarn.lock | 3 +- 10 files changed, 154 insertions(+), 62 deletions(-) create mode 100644 yarn-project/p2p/src/errors/index.ts create mode 100644 yarn-project/p2p/src/errors/reqresp.error.ts create mode 100644 yarn-project/validator-client/src/errors/index.ts create mode 100644 yarn-project/validator-client/src/errors/validator.error.ts create mode 100644 yarn-project/validator-client/src/validator.test.ts diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index 512538585b1..c46adb23f26 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -172,10 +172,10 @@ describe('e2e_p2p_network', () => { /** * Birds eye overview of the test * 1. We spin up x nodes - * 2. We turn off receiving a tx via gossip from one of the nodes - * 3. We send a transaction and gossip it to other nodes - * 4. This node will receive an attestation that it does not have the data for - * 5. It will request this data over the p2p layer + * 2. We turn off receiving a tx via gossip from two of the nodes + * 3. We send a transactions and gossip it to other nodes + * 4. The disabled nodes will receive an attestation that it does not have the data for + * 5. They will request this data over the p2p layer * 6. We receive all of the attestations that we need and we produce the block * * Note: we do not attempt to let this node produce a block, as it will not have received any transactions @@ -197,14 +197,17 @@ describe('e2e_p2p_network', () => { // wait a bit for peers to discover each other await sleep(4000); - // Replace the p2p node implementation of one of the nodes with a spy such that it does not store transactions that are gossiped to it + // Replace the p2p node implementation of some of the nodes with a spy such that it does not store transactions that are gossiped to it // Original implementation of `processTxFromPeer` will store received transactions in the tx pool. - const nodeToTurnOffTxGossip = 0; - jest - .spyOn((nodes[nodeToTurnOffTxGossip] as any).p2pClient.p2pService, 'processTxFromPeer') - .mockImplementation((): Promise => { - return Promise.resolve(); - }); + // We have chosen nodes 0,2 as they do not get chosen to be the sequencer in this test ( node 1 does ). + const nodeToTurnOffTxGossip = [0, 2]; + for (const nodeIndex of nodeToTurnOffTxGossip) { + jest + .spyOn((nodes[nodeIndex] as any).p2pClient.p2pService, 'processTxFromPeer') + .mockImplementation((): Promise => { + return Promise.resolve(); + }); + } // Only submit transactions to the first two nodes, so that we avoid our sequencer with a mocked p2p layer being picked to produce a block. // If the shuffling algorithm changes, then this will need to be updated. diff --git a/yarn-project/p2p/src/errors/index.ts b/yarn-project/p2p/src/errors/index.ts new file mode 100644 index 00000000000..01b77d2a6a2 --- /dev/null +++ b/yarn-project/p2p/src/errors/index.ts @@ -0,0 +1 @@ +export * from './reqresp.error.js'; diff --git a/yarn-project/p2p/src/errors/reqresp.error.ts b/yarn-project/p2p/src/errors/reqresp.error.ts new file mode 100644 index 00000000000..1349205cd74 --- /dev/null +++ b/yarn-project/p2p/src/errors/reqresp.error.ts @@ -0,0 +1,14 @@ +import { type ReqRespSubProtocol, TX_REQ_PROTOCOL } from '../service/reqresp/interface.js'; + +export class ReqRespError extends Error { + constructor(protocol: ReqRespSubProtocol, message: string) { + super(message); + } +} + +// TODO(md): think about what these errors should ideally be +export class TxHandlerReqRespError extends ReqRespError { + constructor() { + super(TX_REQ_PROTOCOL, 'Could not perform tx handler request response'); + } +} diff --git a/yarn-project/p2p/src/service/reqresp/interface.ts b/yarn-project/p2p/src/service/reqresp/interface.ts index 39f27b6268f..5ae61d0389d 100644 --- a/yarn-project/p2p/src/service/reqresp/interface.ts +++ b/yarn-project/p2p/src/service/reqresp/interface.ts @@ -3,9 +3,9 @@ import { Tx, TxHash } from '@aztec/circuit-types'; /* * Request Response Sub Protocols */ -export const PING_PROTOCOL = '/aztec/ping/0.1.0'; -export const STATUS_PROTOCOL = '/aztec/status/0.1.0'; -export const TX_REQ_PROTOCOL = '/aztec/tx_req/0.1.0'; +export const PING_PROTOCOL = '/aztec/req/ping/0.1.0'; +export const STATUS_PROTOCOL = '/aztec/req/status/0.1.0'; +export const TX_REQ_PROTOCOL = '/aztec/req/tx/0.1.0'; // Sum type for sub protocols export type ReqRespSubProtocol = typeof PING_PROTOCOL | typeof STATUS_PROTOCOL | typeof TX_REQ_PROTOCOL; diff --git a/yarn-project/validator-client/package.json b/yarn-project/validator-client/package.json index e89785cf9dc..23ca3b59106 100644 --- a/yarn-project/validator-client/package.json +++ b/yarn-project/validator-client/package.json @@ -72,6 +72,7 @@ "@types/jest": "^29.5.0", "@types/node": "^18.7.23", "jest": "^29.5.0", + "jest-mock-extended": "^3.0.7", "ts-node": "^10.9.1", "typescript": "^5.0.4" }, diff --git a/yarn-project/validator-client/src/errors/index.ts b/yarn-project/validator-client/src/errors/index.ts new file mode 100644 index 00000000000..00a5c872c01 --- /dev/null +++ b/yarn-project/validator-client/src/errors/index.ts @@ -0,0 +1 @@ +export * from './validator.error.js'; diff --git a/yarn-project/validator-client/src/errors/validator.error.ts b/yarn-project/validator-client/src/errors/validator.error.ts new file mode 100644 index 00000000000..5cc3929962e --- /dev/null +++ b/yarn-project/validator-client/src/errors/validator.error.ts @@ -0,0 +1,19 @@ +import { type TxHash } from '@aztec/circuit-types/tx_hash'; + +export class ValidatorError extends Error { + constructor(message: string) { + super(message); + } +} + +export class AttestationTimeoutError extends ValidatorError { + constructor(numberOfRequiredAttestations: number, slot: bigint) { + super(`Timeout waiting for ${numberOfRequiredAttestations} attestations for slot, ${slot}`); + } +} + +export class TransactionsNotAvailableError extends ValidatorError { + constructor(txHashes: TxHash[]) { + super(`Transactions not available: ${txHashes.join(', ')}`); + } +} diff --git a/yarn-project/validator-client/src/validator.test.ts b/yarn-project/validator-client/src/validator.test.ts new file mode 100644 index 00000000000..ec238e14077 --- /dev/null +++ b/yarn-project/validator-client/src/validator.test.ts @@ -0,0 +1,71 @@ +/** + * Validation logic unit tests + */ +import { TxHash } from '@aztec/circuit-types'; +import { makeHeader } from '@aztec/circuits.js/testing'; +import { EthAddress } from '@aztec/foundation/eth-address'; +import { Fr } from '@aztec/foundation/fields'; +import { type P2P } from '@aztec/p2p'; + +import { describe, expect, it } from '@jest/globals'; +import { type MockProxy, mock } from 'jest-mock-extended'; +import { type PrivateKeyAccount, generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; + +import { makeBlockProposal } from '../../circuit-types/src/p2p/mocks.js'; +import { AttestationTimeoutError, TransactionsNotAvailableError } from './errors/validator.error.js'; +import { ValidatorClient } from './validator.js'; + +describe('ValidationService', () => { + let validatorClient: ValidatorClient; + let p2pClient: MockProxy; + let validatorAccount: PrivateKeyAccount; + + beforeEach(() => { + p2pClient = mock(); + p2pClient.getAttestationsForSlot.mockImplementation(() => Promise.resolve([])); + + const validatorPrivateKey = generatePrivateKey(); + validatorAccount = privateKeyToAccount(validatorPrivateKey); + + const config = { + validatorPrivateKey: validatorPrivateKey, + attestationPoolingIntervalMs: 1000, + attestationWaitTimeoutMs: 1000, + disableValidator: false, + }; + validatorClient = ValidatorClient.new(config, p2pClient); + }); + + it('Should create a valid block proposal', async () => { + const header = makeHeader(); + const archive = Fr.random(); + const txs = [1, 2, 3, 4, 5].map(() => TxHash.random()); + + const blockProposal = await validatorClient.createBlockProposal(header, archive, txs); + + expect(blockProposal).toBeDefined(); + + const validatorAddress = EthAddress.fromString(validatorAccount.address); + expect(await blockProposal.getSender()).toEqual(validatorAddress); + }); + + // TODO: add a test on the sequencer that it can recover in case that this timeout is hit + it('Should a timeout if we do not collect enough attestations in time', async () => { + const proposal = await makeBlockProposal(); + + await expect(validatorClient.collectAttestations(proposal, 2)).rejects.toThrow(AttestationTimeoutError); + }); + + it('Should throw an error if the transactions are not available', async () => { + const proposal = await makeBlockProposal(); + + // mock the p2pClient.getTxStatus to return undefined for all transactions + p2pClient.getTxStatus.mockImplementation(() => undefined); + // Mock the p2pClient.requestTxs to return undefined for all transactions + p2pClient.requestTxs.mockImplementation(() => Promise.resolve([undefined])); + + await expect(validatorClient.ensureTransactionsAreAvailable(proposal)).rejects.toThrow( + TransactionsNotAvailableError, + ); + }); +}); diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index 838654160ca..a4ccd25f6ba 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -7,6 +7,7 @@ import { type P2P } from '@aztec/p2p'; import { type ValidatorClientConfig } from './config.js'; import { ValidationService } from './duties/validation_service.js'; +import { AttestationTimeoutError, TransactionsNotAvailableError } from './errors/validator.error.js'; import { type ValidatorKeyStore } from './key_store/interface.js'; import { LocalKeyStore } from './key_store/local_key_store.js'; @@ -18,7 +19,6 @@ export interface Validator { createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise; attestToProposal(proposal: BlockProposal): void; - // TODO(md): possible abstraction leak broadcastBlockProposal(proposal: BlockProposal): void; collectAttestations(proposal: BlockProposal, numberOfRequiredAttestations: number): Promise; } @@ -88,33 +88,20 @@ export class ValidatorClient implements Validator { */ async ensureTransactionsAreAvailable(proposal: BlockProposal) { const txHashes: TxHash[] = proposal.txs; + const transactionStatuses = await Promise.all(txHashes.map(txHash => this.p2pClient.getTxStatus(txHash))); - const transactionStatuses = txHashes.map(txHash => this.p2pClient.getTxStatus(txHash)); - const haveAllTxs = transactionStatuses.every(tx => tx === 'pending' || tx === 'mined'); + const missingTxs = txHashes.filter((_, index) => !['pending', 'mined'].includes(transactionStatuses[index] ?? '')); - // Only in an if statement here for logging purposes - if (!haveAllTxs) { - const missingTxs: TxHash[] = txHashes - .map((_, index) => { - if (!transactionStatuses[index]) { - return txHashes[index]; - } - return undefined; - }) - .filter(tx => tx !== undefined) as TxHash[]; + if (missingTxs.length === 0) { + return; // All transactions are available + } - this.log.verbose( - `Missing ${missingTxs.length} attestations transactions in the tx pool, requesting from the network`, - ); + this.log.verbose(`Missing ${missingTxs.length} transactions in the tx pool, requesting from the network`); - if (missingTxs) { - // If transactions are requested successfully, they will be written into the tx pool - const requestedTxs = await this.p2pClient.requestTxs(missingTxs); - const successfullyRetrievedMissingTxs = requestedTxs.every(tx => tx !== undefined); - if (!successfullyRetrievedMissingTxs) { - throw new Error('Failed to retrieve missing transactions'); - } - } + const requestedTxs = await this.p2pClient.requestTxs(missingTxs); + if (requestedTxs.some(tx => tx === undefined)) { + this.log.error(`Failed to request transactions from the network: ${missingTxs.join(', ')}`); + throw new TransactionsNotAvailableError(missingTxs); } } @@ -131,38 +118,32 @@ export class ValidatorClient implements Validator { proposal: BlockProposal, numberOfRequiredAttestations: number, ): Promise { - // Wait and poll the p2pClients attestation pool for this block - // until we have enough attestations - - const startTime = Date.now(); - + // Wait and poll the p2pClient's attestation pool for this block until we have enough attestations const slot = proposal.header.globalVariables.slotNumber.toBigInt(); - this.log.info(`Waiting for ${numberOfRequiredAttestations} attestations for slot: ${slot}`); - const myAttestation = await this.attestToProposal(proposal); + const myAttestation = await this.validationService.attestToProposal(proposal); + + const startTime = Date.now(); - let attestations: BlockAttestation[] = []; - while (attestations.length < numberOfRequiredAttestations) { - attestations = [myAttestation, ...(await this.p2pClient.getAttestationsForSlot(slot))]; + while (true) { + const attestations = [myAttestation, ...(await this.p2pClient.getAttestationsForSlot(slot))]; - // Rememebr we can subtract 1 from this if we self sign - if (attestations.length < numberOfRequiredAttestations) { - this.log.verbose( - `SEAN: collected ${attestations.length} attestations so far ${numberOfRequiredAttestations} required`, - ); - this.log.verbose(`Waiting ${this.attestationPoolingIntervalMs}ms for more attestations...`); - await sleep(this.attestationPoolingIntervalMs); + if (attestations.length >= numberOfRequiredAttestations) { + this.log.info(`Collected all ${numberOfRequiredAttestations} attestations for slot, ${slot}`); + return attestations; } - // FIX(md): kinna sad looking code - if (Date.now() - startTime > this.attestationWaitTimeoutMs) { + const elapsedTime = Date.now() - startTime; + if (elapsedTime > this.attestationWaitTimeoutMs) { this.log.error(`Timeout waiting for ${numberOfRequiredAttestations} attestations for slot, ${slot}`); - throw new Error(`Timeout waiting for ${numberOfRequiredAttestations} attestations for slot, ${slot}`); + throw new AttestationTimeoutError(numberOfRequiredAttestations, slot); } - } - this.log.info(`Collected all attestations for slot, ${slot}`); - return attestations; + this.log.verbose( + `Collected ${attestations.length} attestations so far, waiting ${this.attestationPoolingIntervalMs}ms for more...`, + ); + await sleep(this.attestationPoolingIntervalMs); + } } } diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index cc8bf108dd1..b91fdb4f6fa 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -1219,6 +1219,7 @@ __metadata: "@types/jest": ^29.5.0 "@types/node": ^18.7.23 jest: ^29.5.0 + jest-mock-extended: ^3.0.7 koa: ^2.14.2 koa-router: ^12.0.0 ts-node: ^10.9.1 @@ -10802,7 +10803,7 @@ __metadata: languageName: node linkType: hard -"jest-mock-extended@npm:^3.0.3, jest-mock-extended@npm:^3.0.4, jest-mock-extended@npm:^3.0.5": +"jest-mock-extended@npm:^3.0.3, jest-mock-extended@npm:^3.0.4, jest-mock-extended@npm:^3.0.5, jest-mock-extended@npm:^3.0.7": version: 3.0.7 resolution: "jest-mock-extended@npm:3.0.7" dependencies: From 045af5a07dc5259cfa5386806fe1b8bc0ad9f28c Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:11:04 +0000 Subject: [PATCH 15/26] clean --- l1-contracts/test/sparta/Sparta.t.sol | 1 - .../src/p2p/block_attestation.ts | 9 ++++---- .../circuit-types/src/p2p/block_proposal.ts | 2 -- yarn-project/p2p/src/client/p2p_client.ts | 19 +++++++++++++++- yarn-project/p2p/src/errors/index.ts | 1 - yarn-project/p2p/src/errors/reqresp.error.ts | 14 ------------ .../src/publisher/l1-publisher.ts | 22 ++++--------------- .../sequencer-client/src/publisher/utils.ts | 17 ++++++++++++++ .../src/sequencer/sequencer.ts | 13 ++--------- .../src/duties/validation_service.ts | 9 ++++---- .../validator-client/src/validator.test.ts | 1 - 11 files changed, 51 insertions(+), 57 deletions(-) delete mode 100644 yarn-project/p2p/src/errors/index.ts delete mode 100644 yarn-project/p2p/src/errors/reqresp.error.ts create mode 100644 yarn-project/sequencer-client/src/publisher/utils.ts diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index a6f802dc102..72cc4dc82b7 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -184,7 +184,6 @@ contract SpartaTest is DecoderBase { rollup.setupEpoch(); - // TODO: include these in the base block and include in the load function bytes32[] memory txHashes = new bytes32[](0); if (_signatureCount > 0 && ree.proposer != address(0)) { diff --git a/yarn-project/circuit-types/src/p2p/block_attestation.ts b/yarn-project/circuit-types/src/p2p/block_attestation.ts index 47ff33f90a7..e78fa7237c2 100644 --- a/yarn-project/circuit-types/src/p2p/block_attestation.ts +++ b/yarn-project/circuit-types/src/p2p/block_attestation.ts @@ -55,10 +55,7 @@ export class BlockAttestation extends Gossipable { async getSender() { if (!this.sender) { // Recover the sender from the attestation - const payload = serializeToBuffer([this.archive, this.txHashes]); - // TODO(md) - temporarily hashing again to have less changes in the rollup - const hashed = keccak256(payload); - // const payload0x: `0x${string}` = `0x${payload.toString('hex')}`; + const hashed = keccak256(this.getPayload()); const address = await recoverMessageAddress({ message: { raw: hashed }, signature: this.signature.to0xString(), @@ -70,6 +67,10 @@ export class BlockAttestation extends Gossipable { return this.sender; } + getPayload(): Buffer { + return serializeToBuffer([this.archive, this.txHashes]); + } + toBuffer(): Buffer { return serializeToBuffer([this.header, this.archive, this.txHashes.length, this.txHashes, this.signature]); } diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.ts b/yarn-project/circuit-types/src/p2p/block_proposal.ts index 1d74c70212c..e9d06208a01 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.ts @@ -57,8 +57,6 @@ export class BlockProposal extends Gossipable { // performance note(): this signature method requires another hash behind the scenes const hashed = keccak256(this.getPayload()); const address = await recoverMessageAddress({ - // TODO(md): fix this up - // message: { raw: this.p2pMessageIdentifier().to0xString() }, message: { raw: hashed }, signature: this.signature.to0xString(), }); diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 4b079c9d5b3..7534c320164 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -291,12 +291,29 @@ export class P2PClient implements P2P { this.p2pService.registerBlockReceivedCallback(handler); } - // TODO: this will need a timeout + retry mechanism to make sure that we can retreive things on time + /** + * Requests the transactions with the given hashes from the network. + * + * If a transaction can be retrieved, it will be returned, if not an undefined + * will be returned. In place. + * + * @param txHashes - The hashes of the transactions to request. + * @returns A promise that resolves to an array of transactions or undefined. + */ public requestTxs(txHashes: TxHash[]): Promise<(Tx | undefined)[]> { const requestPromises = txHashes.map(txHash => this.requestTxByHash(txHash)); return Promise.all(requestPromises); } + /** + * Uses the Request Response protocol to request a transaction from the network. + * + * If the underlying request response protocol fails, then we return undefined. + * If it succeeds then we add the transaction to our transaction pool and return. + * + * @param txHash - The hash of the transaction to request. + * @returns A promise that resolves to a transaction or undefined. + */ public async requestTxByHash(txHash: TxHash): Promise { const tx = await this.p2pService.sendRequest(TX_REQ_PROTOCOL, txHash); diff --git a/yarn-project/p2p/src/errors/index.ts b/yarn-project/p2p/src/errors/index.ts deleted file mode 100644 index 01b77d2a6a2..00000000000 --- a/yarn-project/p2p/src/errors/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './reqresp.error.js'; diff --git a/yarn-project/p2p/src/errors/reqresp.error.ts b/yarn-project/p2p/src/errors/reqresp.error.ts deleted file mode 100644 index 1349205cd74..00000000000 --- a/yarn-project/p2p/src/errors/reqresp.error.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { type ReqRespSubProtocol, TX_REQ_PROTOCOL } from '../service/reqresp/interface.js'; - -export class ReqRespError extends Error { - constructor(protocol: ReqRespSubProtocol, message: string) { - super(message); - } -} - -// TODO(md): think about what these errors should ideally be -export class TxHandlerReqRespError extends ReqRespError { - constructor() { - super(TX_REQ_PROTOCOL, 'Could not perform tx handler request response'); - } -} diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index d1a59a138af..02320b0f782 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -33,6 +33,7 @@ import type * as chains from 'viem/chains'; import { type PublisherConfig, type TxSenderConfig } from './config.js'; import { L1PublisherMetrics } from './l1-publisher-metrics.js'; +import { prettyLogVeimError } from './utils.js'; /** * Stats for a sent transaction. @@ -248,7 +249,6 @@ export class L1Publisher { * @param block - L2 block to publish. * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise. */ - // TODO: rename propose public async processL2Block(block: L2Block, attestations?: Signature[], txHashes?: TxHash[]): Promise { const ctx = { blockNumber: block.number, @@ -256,8 +256,7 @@ export class L1Publisher { blockHash: block.hash().toString(), }; - // TODO: move this to take in the proposal to get the digest - rather than manually - const tempDigest = keccak256(serializeToBuffer(block.archive.root, txHashes ?? [])); + const digest = keccak256(serializeToBuffer(block.archive.root, txHashes ?? [])); const proposeTxArgs = { header: block.header.toBuffer(), archive: block.archive.root.toBuffer(), @@ -279,8 +278,7 @@ export class L1Publisher { // By simulation issue, I mean the fact that the block.timestamp is equal to the last block, not the next, which // make time consistency checks break. await this.validateBlockForSubmission(block.header, { - // digest: block.archive.root.toBuffer(), // THIS IS NOT THE DIGEST ANYMORE!!!!! - digest: tempDigest, + digest, signatures: attestations ?? [], }); @@ -534,19 +532,7 @@ export class L1Publisher { }); } } catch (err) { - if (err instanceof BaseError) { - const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); - if (revertError instanceof ContractFunctionRevertedError) { - // TODO: turn this into a function - const errorName = revertError.data?.errorName ?? ''; - const args = - revertError.metaMessages && revertError.metaMessages?.length > 1 - ? revertError.metaMessages[1].trimStart() - : ''; - this.log.error(`propose failed with "${errorName}${args}"`); - return undefined; - } - } + prettyLogVeimError(err, this.log); this.log.error(`Rollup publish failed`, err); return undefined; } diff --git a/yarn-project/sequencer-client/src/publisher/utils.ts b/yarn-project/sequencer-client/src/publisher/utils.ts new file mode 100644 index 00000000000..7e23aa0c878 --- /dev/null +++ b/yarn-project/sequencer-client/src/publisher/utils.ts @@ -0,0 +1,17 @@ +import { Logger } from "@aztec/foundation/log"; +import { BaseError, ContractFunctionRevertedError } from "viem"; + + +export function prettyLogVeimError(err: any, logger: Logger) { + if (err instanceof BaseError) { + const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); + if (revertError instanceof ContractFunctionRevertedError) { + const errorName = revertError.data?.errorName ?? ''; + const args = + revertError.metaMessages && revertError.metaMessages?.length > 1 + ? revertError.metaMessages[1].trimStart() + : ''; + logger.debug(`canProposeAtTime failed with "${errorName}${args}"`); + } + } +} \ No newline at end of file diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index f57720ea370..bcf8e0f6d78 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -38,6 +38,7 @@ import { type L1Publisher } from '../publisher/l1-publisher.js'; import { type TxValidatorFactory } from '../tx_validator/tx_validator_factory.js'; import { type SequencerConfig } from './config.js'; import { SequencerMetrics } from './metrics.js'; +import { prettyLogVeimError } from '../publisher/utils.js'; export type ShouldProposeArgs = { pendingTxsCount?: number; @@ -311,17 +312,7 @@ export class Sequencer { this.log.debug(`Can propose block ${proposalBlockNumber} at slot ${slot}`); return slot; } catch (err) { - if (err instanceof BaseError) { - const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); - if (revertError instanceof ContractFunctionRevertedError) { - const errorName = revertError.data?.errorName ?? ''; - const args = - revertError.metaMessages && revertError.metaMessages?.length > 1 - ? revertError.metaMessages[1].trimStart() - : ''; - this.log.debug(`canProposeAtTime failed with "${errorName}${args}"`); - } - } + prettyLogVeimError(err, this.log); throw err; } } diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index 6da7e816b76..fe2a3727940 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -19,9 +19,9 @@ export class ValidationService { * @returns A block proposal signing the above information (not the current implementation!!!) */ async createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { - // Note: just signing the archive for now + + // NOTE: just signing the archive and txs for now const payload = serializeToBuffer([archive, txs]); - // TODO(temp hash it together before signing) const hashed = keccak256(payload); const sig = await this.keyStore.sign(hashed); @@ -31,14 +31,15 @@ export class ValidationService { /** * Attest to the given block proposal constructed by the current sequencer * + * NOTE: This is just a blind signing. + * We assume that the proposal is valid and DA guarantees have been checked previously. + * * @param proposal - The proposal to attest to * @returns attestation */ async attestToProposal(proposal: BlockProposal): Promise { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct - // TODO: in the function before this, check that all of the txns exist in the payload - const buf = keccak256(proposal.getPayload()); const sig = await this.keyStore.sign(buf); return new BlockAttestation(proposal.header, proposal.archive, proposal.txs, sig); diff --git a/yarn-project/validator-client/src/validator.test.ts b/yarn-project/validator-client/src/validator.test.ts index ec238e14077..4802656e5ce 100644 --- a/yarn-project/validator-client/src/validator.test.ts +++ b/yarn-project/validator-client/src/validator.test.ts @@ -49,7 +49,6 @@ describe('ValidationService', () => { expect(await blockProposal.getSender()).toEqual(validatorAddress); }); - // TODO: add a test on the sequencer that it can recover in case that this timeout is hit it('Should a timeout if we do not collect enough attestations in time', async () => { const proposal = await makeBlockProposal(); From 73d26ec97a93c3f58e5b4cefc854b3a203f4c718 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Fri, 6 Sep 2024 22:29:41 +0000 Subject: [PATCH 16/26] =?UTF-8?q?=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- l1-contracts/src/core/Rollup.sol | 1 - l1-contracts/src/core/interfaces/IRollup.sol | 2 -- .../src/publisher/l1-publisher.ts | 3 +-- .../sequencer-client/src/publisher/utils.ts | 26 +++++++++---------- .../src/sequencer/sequencer.ts | 4 +-- .../src/duties/validation_service.ts | 1 - 6 files changed, 14 insertions(+), 23 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index fad78591128..e8ebb009920 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -182,7 +182,6 @@ contract Rollup is Leonidas, IRollup, ITestRollup { * @param _signatures - Signatures from the validators * @param _body - The body of the L2 block */ - // Temp change name to fix viem issue function proposeWithBody( bytes calldata _header, bytes32 _archive, diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index d6f60be1a47..23c3012372b 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -34,8 +34,6 @@ interface IRollup { function OUTBOX() external view returns (IOutbox); - // Temp: turns out there is a viem bug where it cannot differentiate between the two - // different types function proposeWithBody( bytes calldata _header, bytes32 _archive, diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 02320b0f782..4c1937a6b79 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -13,7 +13,6 @@ import { type TelemetryClient } from '@aztec/telemetry-client'; import pick from 'lodash.pick'; import { - BaseError, ContractFunctionRevertedError, type GetContractReturnType, type Hex, @@ -503,7 +502,7 @@ export class L1Publisher { // We almost always want to skip simulation here if we are not already within the slot, else we will be one slot ahead // See comment attached to static SKIP_SIMULATION definition if (!L1Publisher.SKIP_SIMULATION) { - const simulationResult = await this.rollupContract.simulate.proposeWithBody(args, { + await this.rollupContract.simulate.proposeWithBody(args, { account: this.account, }); } diff --git a/yarn-project/sequencer-client/src/publisher/utils.ts b/yarn-project/sequencer-client/src/publisher/utils.ts index 7e23aa0c878..13842102a2c 100644 --- a/yarn-project/sequencer-client/src/publisher/utils.ts +++ b/yarn-project/sequencer-client/src/publisher/utils.ts @@ -1,17 +1,15 @@ -import { Logger } from "@aztec/foundation/log"; -import { BaseError, ContractFunctionRevertedError } from "viem"; +import { type Logger } from '@aztec/foundation/log'; +import { BaseError, ContractFunctionRevertedError } from 'viem'; export function prettyLogVeimError(err: any, logger: Logger) { - if (err instanceof BaseError) { - const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); - if (revertError instanceof ContractFunctionRevertedError) { - const errorName = revertError.data?.errorName ?? ''; - const args = - revertError.metaMessages && revertError.metaMessages?.length > 1 - ? revertError.metaMessages[1].trimStart() - : ''; - logger.debug(`canProposeAtTime failed with "${errorName}${args}"`); - } - } -} \ No newline at end of file + if (err instanceof BaseError) { + const revertError = err.walk(err => err instanceof ContractFunctionRevertedError); + if (revertError instanceof ContractFunctionRevertedError) { + const errorName = revertError.data?.errorName ?? ''; + const args = + revertError.metaMessages && revertError.metaMessages?.length > 1 ? revertError.metaMessages[1].trimStart() : ''; + logger.debug(`canProposeAtTime failed with "${errorName}${args}"`); + } + } +} diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index bcf8e0f6d78..611994cdaec 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -30,15 +30,13 @@ import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec import { type ValidatorClient } from '@aztec/validator-client'; import { type WorldStateStatus, type WorldStateSynchronizer } from '@aztec/world-state'; -import { BaseError, ContractFunctionRevertedError } from 'viem'; - import { type BlockBuilderFactory } from '../block_builder/index.js'; import { type GlobalVariableBuilder } from '../global_variable_builder/global_builder.js'; import { type L1Publisher } from '../publisher/l1-publisher.js'; +import { prettyLogVeimError } from '../publisher/utils.js'; import { type TxValidatorFactory } from '../tx_validator/tx_validator_factory.js'; import { type SequencerConfig } from './config.js'; import { SequencerMetrics } from './metrics.js'; -import { prettyLogVeimError } from '../publisher/utils.js'; export type ShouldProposeArgs = { pendingTxsCount?: number; diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index fe2a3727940..1115d72208f 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -19,7 +19,6 @@ export class ValidationService { * @returns A block proposal signing the above information (not the current implementation!!!) */ async createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { - // NOTE: just signing the archive and txs for now const payload = serializeToBuffer([archive, txs]); const hashed = keccak256(payload); From d358228317434e03594f3fcdcfe7182c837732e1 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:28:36 +0000 Subject: [PATCH 17/26] chore: fix sequencing tests --- .../src/sequencer/sequencer.test.ts | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 73b441a58eb..39fda5b0ae2 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -180,6 +180,7 @@ describe('sequencer', () => { it('builds a block out of a single tx', async () => { const tx = mockTxForRollup(); tx.data.constants.txContext.chainId = chainId; + const txHash = tx.getTxHash(); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, @@ -205,13 +206,14 @@ describe('sequencer', () => { ); // Ok, we have an issue that we never actually call the process L2 block expect(publisher.processL2Block).toHaveBeenCalledTimes(1); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), [txHash]); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); it('builds a block when it is their turn', async () => { const tx = mockTxForRollup(); tx.data.constants.txContext.chainId = chainId; + const txHash = tx.getTxHash(); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -253,16 +255,19 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), [txHash]); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); it('builds a block out of several txs rejecting double spends', async () => { + const doubleSpendTxIndex = 1; const txs = [mockTxForRollup(0x10000), mockTxForRollup(0x20000), mockTxForRollup(0x30000)]; txs.forEach(tx => { tx.data.constants.txContext.chainId = chainId; }); - const doubleSpendTx = txs[1]; + const validTxHashes = txs.filter((_, i) => i !== doubleSpendTxIndex).map(tx => tx.getTxHash()); + + const doubleSpendTx = txs[doubleSpendTxIndex]; const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -293,17 +298,20 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), validTxHashes); expect(p2p.deleteTxs).toHaveBeenCalledWith([doubleSpendTx.getTxHash()]); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); it('builds a block out of several txs rejecting incorrect chain ids', async () => { + const invalidChainTxIndex = 1; const txs = [mockTxForRollup(0x10000), mockTxForRollup(0x20000), mockTxForRollup(0x30000)]; txs.forEach(tx => { tx.data.constants.txContext.chainId = chainId; }); - const invalidChainTx = txs[1]; + const invalidChainTx = txs[invalidChainTxIndex]; + const validTxHashes = txs.filter((_, i) => i !== invalidChainTxIndex).map(tx => tx.getTxHash()); + const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -329,16 +337,20 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), validTxHashes); expect(p2p.deleteTxs).toHaveBeenCalledWith([invalidChainTx.getTxHash()]); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); it('builds a block out of several txs dropping the ones that go over max size', async () => { + const invalidTransactionIndex = 1; + const txs = [mockTxForRollup(0x10000), mockTxForRollup(0x20000), mockTxForRollup(0x30000)]; txs.forEach(tx => { tx.data.constants.txContext.chainId = chainId; }); + const validTxHashes = txs.filter((_, i) => i !== invalidTransactionIndex).map(tx => tx.getTxHash()); + const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -354,8 +366,9 @@ describe('sequencer', () => { globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); // We make txs[1] too big to fit - (txs[1] as Writeable).unencryptedLogs = UnencryptedTxL2Logs.random(2, 4); - (txs[1].unencryptedLogs.functionLogs[0].logs[0] as Writeable).data = randomBytes(1024 * 1022); + (txs[invalidTransactionIndex] as Writeable).unencryptedLogs = UnencryptedTxL2Logs.random(2, 4); + (txs[invalidTransactionIndex].unencryptedLogs.functionLogs[0].logs[0] as Writeable).data = + randomBytes(1024 * 1022); await sequencer.initialSync(); await sequencer.work(); @@ -365,7 +378,7 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), validTxHashes); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -401,11 +414,14 @@ describe('sequencer', () => { // block is not built with 3 txs p2p.getTxs.mockReturnValueOnce(txs.slice(0, 3)); + await sequencer.work(); expect(blockSimulator.startNewBlock).toHaveBeenCalledTimes(0); // block is built with 4 txs p2p.getTxs.mockReturnValueOnce(txs.slice(0, 4)); + const txHashes = txs.slice(0, 4).map(tx => tx.getTxHash()); + await sequencer.work(); expect(blockSimulator.startNewBlock).toHaveBeenCalledWith( 4, @@ -413,7 +429,7 @@ describe('sequencer', () => { Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledTimes(1); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), txHashes); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -464,7 +480,7 @@ describe('sequencer', () => { Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledTimes(1); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), []); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -506,7 +522,9 @@ describe('sequencer', () => { sequencer.flush(); // block is built with 3 txs - p2p.getTxs.mockReturnValueOnce(txs.slice(0, 3)); + const postFlushTxs = txs.slice(0, 3); + p2p.getTxs.mockReturnValueOnce(postFlushTxs); + const postFlushTxHashes = postFlushTxs.map(tx => tx.getTxHash()); await sequencer.work(); expect(blockSimulator.startNewBlock).toHaveBeenCalledTimes(1); expect(blockSimulator.startNewBlock).toHaveBeenCalledWith( @@ -516,7 +534,7 @@ describe('sequencer', () => { ); expect(publisher.processL2Block).toHaveBeenCalledTimes(1); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures(), postFlushTxHashes); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); From 2e3f80bb483612e5e569c4d638e95d885e4a43c9 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sat, 7 Sep 2024 17:38:15 +0000 Subject: [PATCH 18/26] fmt solidity --- l1-contracts/src/core/Rollup.sol | 1 - l1-contracts/test/sparta/Sparta.t.sol | 2 -- 2 files changed, 3 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index e8ebb009920..b0b1aef496c 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -443,7 +443,6 @@ contract Rollup is Leonidas, IRollup, ITestRollup { HeaderLib.Header memory header = HeaderLib.decode(_header); setupEpoch(); - // TODO: make function for this bytes32 digest = keccak256(abi.encodePacked(_archive, _txHashes)); _validateHeader({ _header: header, diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index 72cc4dc82b7..0528e475c03 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -166,8 +166,6 @@ contract SpartaTest is DecoderBase { DecoderBase.Full memory full = load(_name); bytes memory header = full.block.header; bytes32 archive = full.block.archive; - // TODO(md): get the tx hashes from the block - but we do not have them now - // Come back to this bytes memory body = full.block.body; StructToAvoidDeepStacks memory ree; From 1bde1fe6f9a0f9c7eef37dd8c17eb69858ef029d Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sun, 8 Sep 2024 08:51:29 +0000 Subject: [PATCH 19/26] fix: test hash --- yarn-project/circuit-types/src/p2p/mocks.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yarn-project/circuit-types/src/p2p/mocks.ts b/yarn-project/circuit-types/src/p2p/mocks.ts index f4646e20919..0c57accf546 100644 --- a/yarn-project/circuit-types/src/p2p/mocks.ts +++ b/yarn-project/circuit-types/src/p2p/mocks.ts @@ -3,6 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type PrivateKeyAccount } from 'viem'; +import { keccak256 } from 'viem'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; import { TxHash } from '../tx/tx_hash.js'; @@ -16,7 +17,8 @@ export const makeBlockProposal = async (signer?: PrivateKeyAccount): Promise TxHash.random()); - const signature = Signature.from0xString(await signer.signMessage({ message: { raw: archive.toString() } })); + const hash = keccak256(serializeToBuffer([archive, txs])); + const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } })); return new BlockProposal(blockHeader, archive, txs, signature); }; @@ -28,7 +30,7 @@ export const makeBlockAttestation = async (signer?: PrivateKeyAccount): Promise< const blockHeader = makeHeader(1); const archive = Fr.random(); const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()); - const hash: `0x${string}` = `0x${serializeToBuffer([archive, txs]).toString('hex')}`; + const hash = keccak256(serializeToBuffer([archive, txs])); const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } })); return new BlockAttestation(blockHeader, archive, txs, signature); From 29fa0909e97dbfd62afcad341b813795e396d8d3 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sun, 8 Sep 2024 09:21:57 +0000 Subject: [PATCH 20/26] fix: attestations are requested based on their proposal not just slot --- .../src/attestation_pool/attestation_pool.ts | 3 +- .../memory_attestation_pool.test.ts | 59 +++++++++++++++-- .../memory_attestation_pool.ts | 64 +++++++++++++++---- .../p2p/src/attestation_pool/mocks.ts | 7 +- yarn-project/p2p/src/client/p2p_client.ts | 7 +- .../validator-client/src/validator.ts | 3 +- 6 files changed, 117 insertions(+), 26 deletions(-) diff --git a/yarn-project/p2p/src/attestation_pool/attestation_pool.ts b/yarn-project/p2p/src/attestation_pool/attestation_pool.ts index a4fcb993c6e..cdfe8729911 100644 --- a/yarn-project/p2p/src/attestation_pool/attestation_pool.ts +++ b/yarn-project/p2p/src/attestation_pool/attestation_pool.ts @@ -36,7 +36,8 @@ export interface AttestationPool { * Retrieve all of the attestations observed pertaining to a given slot * * @param slot - The slot to query + * @param proposalId - The proposal to query * @return BlockAttestations */ - getAttestationsForSlot(slot: bigint): Promise; + getAttestationsForSlot(slot: bigint, proposalId: string): Promise; } diff --git a/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts b/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts index 37e3195c309..21a10391f13 100644 --- a/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts +++ b/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts @@ -1,3 +1,5 @@ +import { Fr } from '@aztec/foundation/fields'; + import { type PrivateKeyAccount } from 'viem'; import { InMemoryAttestationPool } from './memory_attestation_pool.js'; @@ -16,11 +18,15 @@ describe('MemoryAttestationPool', () => { it('should add attestation to pool', async () => { const slotNumber = 420; - const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber))); + const archive = Fr.random(); + const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive))); + + // TODO(md): this will change across the board + const proposalId = attestations[0].p2pMessageIdentifier.toString(); await ap.addAttestations(attestations); - const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber)); + const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST); expect(retreivedAttestations).toEqual(attestations); @@ -28,7 +34,7 @@ describe('MemoryAttestationPool', () => { // Delete by slot await ap.deleteAttestationsForSlot(BigInt(slotNumber)); - const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber)); + const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); expect(retreivedAttestationsAfterDelete.length).toBe(0); }); @@ -40,8 +46,9 @@ describe('MemoryAttestationPool', () => { for (const attestation of attestations) { const slot = attestation.header.globalVariables.slotNumber; + const proposalId = attestation.p2pMessageIdentifier.toString(); - const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt()); + const retreivedAttestations = await ap.getAttestationsForSlot(slot.toBigInt(), proposalId); expect(retreivedAttestations.length).toBe(1); expect(retreivedAttestations[0]).toEqual(attestation); expect(retreivedAttestations[0].header.globalVariables.slotNumber).toEqual(slot); @@ -50,17 +57,55 @@ describe('MemoryAttestationPool', () => { it('Should delete attestations', async () => { const slotNumber = 420; - const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber))); + const archive = Fr.random(); + const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive))); + const proposalId = attestations[0].p2pMessageIdentifier.toString(); await ap.addAttestations(attestations); - const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber)); + const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST); expect(retreivedAttestations).toEqual(attestations); await ap.deleteAttestations(attestations); - const gottenAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber)); + const gottenAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); expect(gottenAfterDelete.length).toBe(0); }); + + it('Should blanket delete attestations per slot', async () => { + const slotNumber = 420; + const archive = Fr.random(); + const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive))); + const proposalId = attestations[0].p2pMessageIdentifier.toString(); + + await ap.addAttestations(attestations); + + const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); + expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST); + expect(retreivedAttestations).toEqual(attestations); + + await ap.deleteAttestationsForSlot(BigInt(slotNumber)); + + const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); + expect(retreivedAttestationsAfterDelete.length).toBe(0); + }); + + it('Should blanket delete attestations per slot and proposal', async () => { + const slotNumber = 420; + const archive = Fr.random(); + const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive))); + const proposalId = attestations[0].p2pMessageIdentifier.toString(); + + await ap.addAttestations(attestations); + + const retreivedAttestations = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); + expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST); + expect(retreivedAttestations).toEqual(attestations); + + await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId); + + const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlot(BigInt(slotNumber), proposalId); + expect(retreivedAttestationsAfterDelete.length).toBe(0); + }); }); diff --git a/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.ts b/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.ts index 524a399aece..c917c8072c8 100644 --- a/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.ts +++ b/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.ts @@ -4,19 +4,21 @@ import { createDebugLogger } from '@aztec/foundation/log'; import { type AttestationPool } from './attestation_pool.js'; export class InMemoryAttestationPool implements AttestationPool { - private attestations: Map>; + private attestations: Map>>; constructor(private log = createDebugLogger('aztec:attestation_pool')) { this.attestations = new Map(); } - public getAttestationsForSlot(slot: bigint): Promise { + public getAttestationsForSlot(slot: bigint, proposalId: string): Promise { const slotAttestationMap = this.attestations.get(slot); if (slotAttestationMap) { - return Promise.resolve(Array.from(slotAttestationMap.values())); - } else { - return Promise.resolve([]); + const proposalAttestationMap = slotAttestationMap.get(proposalId); + if (proposalAttestationMap) { + return Promise.resolve(Array.from(proposalAttestationMap.values())); + } } + return Promise.resolve([]); } public async addAttestations(attestations: BlockAttestation[]): Promise { @@ -24,10 +26,14 @@ export class InMemoryAttestationPool implements AttestationPool { // Perf: order and group by slot before insertion const slotNumber = attestation.header.globalVariables.slotNumber; + // TODO(md): change the name on this, get the data from the underlying proposal, we want it cached so less hashing + const proposalId = attestation.p2pMessageIdentifier.toString(); + const address = await attestation.getSender(); const slotAttestationMap = getSlotOrDefault(this.attestations, slotNumber.toBigInt()); - slotAttestationMap.set(address.toString(), attestation); + const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId); + proposalAttestationMap.set(address.toString(), attestation); this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`); } @@ -40,14 +46,27 @@ export class InMemoryAttestationPool implements AttestationPool { return Promise.resolve(); } + public deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise { + const slotAttestationMap = this.attestations.get(slot); + if (slotAttestationMap) { + slotAttestationMap.delete(proposalId); + this.log.verbose(`Removed attestation for slot ${slot}`); + } + return Promise.resolve(); + } + public async deleteAttestations(attestations: BlockAttestation[]): Promise { for (const attestation of attestations) { const slotNumber = attestation.header.globalVariables.slotNumber; const slotAttestationMap = this.attestations.get(slotNumber.toBigInt()); if (slotAttestationMap) { - const address = await attestation.getSender(); - slotAttestationMap.delete(address.toString()); - this.log.verbose(`Deleted attestation for slot ${slotNumber} from ${address}`); + const proposalId = attestation.p2pMessageIdentifier.toString(); + const proposalAttestationMap = getProposalOrDefault(slotAttestationMap, proposalId); + if (proposalAttestationMap) { + const address = await attestation.getSender(); + proposalAttestationMap.delete(address.toString()); + this.log.debug(`Deleted attestation for slot ${slotNumber} from ${address}`); + } } } return Promise.resolve(); @@ -58,13 +77,34 @@ export class InMemoryAttestationPool implements AttestationPool { * Get Slot or Default * * Fetch the slot mapping, if it does not exist, then create a mapping and return it + * @param map - The map to fetch from + * @param slot - The slot to fetch + * @returns The slot mapping */ function getSlotOrDefault( - map: Map>, + map: Map>>, slot: bigint, -): Map { +): Map> { if (!map.has(slot)) { - map.set(slot, new Map()); + map.set(slot, new Map>()); } return map.get(slot)!; } + +/** + * Get Proposal or Default + * + * Fetch the proposal mapping, if it does not exist, then create a mapping and return it + * @param map - The map to fetch from + * @param proposalId - The proposal id to fetch + * @returns The proposal mapping + */ +function getProposalOrDefault( + map: Map>, + proposalId: string, +): Map { + if (!map.has(proposalId)) { + map.set(proposalId, new Map()); + } + return map.get(proposalId)!; +} diff --git a/yarn-project/p2p/src/attestation_pool/mocks.ts b/yarn-project/p2p/src/attestation_pool/mocks.ts index 00194d52b96..1730a236102 100644 --- a/yarn-project/p2p/src/attestation_pool/mocks.ts +++ b/yarn-project/p2p/src/attestation_pool/mocks.ts @@ -22,10 +22,13 @@ export const generateAccount = () => { * @param slot The slot number the attestation is for * @returns A Block Attestation */ -export const mockAttestation = async (signer: PrivateKeyAccount, slot: number = 0): Promise => { +export const mockAttestation = async ( + signer: PrivateKeyAccount, + slot: number = 0, + archive: Fr = Fr.random(), +): Promise => { // Use arbitrary numbers for all other than slot const header = makeHeader(1, 2, slot); - const archive = Fr.random(); const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()); const message: `0x${string}` = `0x${serializeToBuffer([archive, txs]).toString('hex')}`; diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 7534c320164..736cc20cf25 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -58,9 +58,10 @@ export interface P2P { * Queries the Attestation pool for attestations for the given slot * * @param slot - the slot to query + * @param proposalId - the proposal id to query * @returns BlockAttestations */ - getAttestationsForSlot(slot: bigint): Promise; + getAttestationsForSlot(slot: bigint, proposalId: string): Promise; /** * Registers a callback from the validator client that determines how to behave when @@ -281,8 +282,8 @@ export class P2PClient implements P2P { return this.p2pService.propagate(proposal); } - public getAttestationsForSlot(slot: bigint): Promise { - return Promise.resolve(this.attestationPool.getAttestationsForSlot(slot)); + public getAttestationsForSlot(slot: bigint, proposalId: string): Promise { + return Promise.resolve(this.attestationPool.getAttestationsForSlot(slot, proposalId)); } // REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963 diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index a4ccd25f6ba..ff5a681ce4c 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -122,12 +122,13 @@ export class ValidatorClient implements Validator { const slot = proposal.header.globalVariables.slotNumber.toBigInt(); this.log.info(`Waiting for ${numberOfRequiredAttestations} attestations for slot: ${slot}`); + const proposalId = proposal.p2pMessageIdentifier.toString(); const myAttestation = await this.validationService.attestToProposal(proposal); const startTime = Date.now(); while (true) { - const attestations = [myAttestation, ...(await this.p2pClient.getAttestationsForSlot(slot))]; + const attestations = [myAttestation, ...(await this.p2pClient.getAttestationsForSlot(slot, proposalId))]; if (attestations.length >= numberOfRequiredAttestations) { this.log.info(`Collected all ${numberOfRequiredAttestations} attestations for slot, ${slot}`); From 7a50a2b9db37c43cb87d7da60c79dcdab5953e2d Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Sun, 8 Sep 2024 10:16:15 +0000 Subject: [PATCH 21/26] exp: adjust test nodes --- yarn-project/end-to-end/src/e2e_p2p_network.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index c46adb23f26..6caf8f6bec4 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -199,8 +199,8 @@ describe('e2e_p2p_network', () => { // Replace the p2p node implementation of some of the nodes with a spy such that it does not store transactions that are gossiped to it // Original implementation of `processTxFromPeer` will store received transactions in the tx pool. - // We have chosen nodes 0,2 as they do not get chosen to be the sequencer in this test ( node 1 does ). - const nodeToTurnOffTxGossip = [0, 2]; + // We have chosen nodes 0,3 as they do not get chosen to be the sequencer in this test. + const nodeToTurnOffTxGossip = [0, 3]; for (const nodeIndex of nodeToTurnOffTxGossip) { jest .spyOn((nodes[nodeIndex] as any).p2pClient.p2pService, 'processTxFromPeer') From 1c2b151c407eeb7cf12b45c58a775a81bb5cf6dd Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 11 Sep 2024 08:56:55 +0000 Subject: [PATCH 22/26] fix: use abi.encode vs encodePacked --- l1-contracts/src/core/Rollup.sol | 2 +- l1-contracts/test/sparta/Sparta.t.sol | 2 +- .../src/p2p/block_attestation.ts | 7 ++-- .../circuit-types/src/p2p/block_proposal.ts | 19 +++++++++-- .../circuit-types/src/p2p/block_utils.ts | 32 +++++++++++++++++++ yarn-project/circuit-types/src/p2p/index.ts | 1 + yarn-project/circuit-types/src/p2p/mocks.ts | 7 ++-- .../foundation/src/buffer/buffer32.ts | 9 ++++++ .../src/publisher/l1-publisher.ts | 4 +-- .../src/duties/validation_service.ts | 9 ++---- 10 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 yarn-project/circuit-types/src/p2p/block_utils.ts diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index b0b1aef496c..ca9aed08f2d 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -443,7 +443,7 @@ contract Rollup is Leonidas, IRollup, ITestRollup { HeaderLib.Header memory header = HeaderLib.decode(_header); setupEpoch(); - bytes32 digest = keccak256(abi.encodePacked(_archive, _txHashes)); + bytes32 digest = keccak256(abi.encode(_archive, _txHashes)); _validateHeader({ _header: header, _signatures: _signatures, diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index 0528e475c03..b0f18cf37b7 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -190,7 +190,7 @@ contract SpartaTest is DecoderBase { SignatureLib.Signature[] memory signatures = new SignatureLib.Signature[](_signatureCount); - bytes32 digest = keccak256(abi.encodePacked(archive, txHashes)); + bytes32 digest = keccak256(abi.encode(archive, txHashes)); for (uint256 i = 0; i < _signatureCount; i++) { signatures[i] = createSignature(validators[i], digest); } diff --git a/yarn-project/circuit-types/src/p2p/block_attestation.ts b/yarn-project/circuit-types/src/p2p/block_attestation.ts index e78fa7237c2..e38effdb368 100644 --- a/yarn-project/circuit-types/src/p2p/block_attestation.ts +++ b/yarn-project/circuit-types/src/p2p/block_attestation.ts @@ -3,9 +3,10 @@ import { Buffer32 } from '@aztec/foundation/buffer'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { keccak256, recoverMessageAddress } from 'viem'; +import { recoverMessageAddress } from 'viem'; import { TxHash } from '../tx/tx_hash.js'; +import { get0xStringHashedSignaturePayload, getSignaturePayload } from './block_utils.js'; import { Gossipable } from './gossipable.js'; import { Signature } from './signature.js'; import { TopicType, createTopicString } from './topic_type.js'; @@ -55,7 +56,7 @@ export class BlockAttestation extends Gossipable { async getSender() { if (!this.sender) { // Recover the sender from the attestation - const hashed = keccak256(this.getPayload()); + const hashed = get0xStringHashedSignaturePayload(this.archive, this.txHashes); const address = await recoverMessageAddress({ message: { raw: hashed }, signature: this.signature.to0xString(), @@ -68,7 +69,7 @@ export class BlockAttestation extends Gossipable { } getPayload(): Buffer { - return serializeToBuffer([this.archive, this.txHashes]); + return getSignaturePayload(this.archive, this.txHashes); } toBuffer(): Buffer { diff --git a/yarn-project/circuit-types/src/p2p/block_proposal.ts b/yarn-project/circuit-types/src/p2p/block_proposal.ts index e9d06208a01..8164e755117 100644 --- a/yarn-project/circuit-types/src/p2p/block_proposal.ts +++ b/yarn-project/circuit-types/src/p2p/block_proposal.ts @@ -3,9 +3,10 @@ import { Buffer32 } from '@aztec/foundation/buffer'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { keccak256, recoverMessageAddress } from 'viem'; +import { recoverMessageAddress } from 'viem'; import { TxHash } from '../tx/tx_hash.js'; +import { get0xStringHashedSignaturePayload, getHashedSignaturePayload, getSignaturePayload } from './block_utils.js'; import { Gossipable } from './gossipable.js'; import { Signature } from './signature.js'; import { TopicType, createTopicString } from './topic_type.js'; @@ -49,13 +50,25 @@ export class BlockProposal extends Gossipable { return BlockProposalHash.fromField(this.archive); } + static async createProposalFromSigner( + header: Header, + archive: Fr, + txs: TxHash[], + payloadSigner: (payload: Buffer) => Promise, + ) { + const hashed = getHashedSignaturePayload(archive, txs); + const sig = await payloadSigner(hashed); + + return new BlockProposal(header, archive, txs, sig); + } + /**Get Sender * Lazily evaluate the sender of the proposal; result is cached */ async getSender() { if (!this.sender) { // performance note(): this signature method requires another hash behind the scenes - const hashed = keccak256(this.getPayload()); + const hashed = get0xStringHashedSignaturePayload(this.archive, this.txs); const address = await recoverMessageAddress({ message: { raw: hashed }, signature: this.signature.to0xString(), @@ -68,7 +81,7 @@ export class BlockProposal extends Gossipable { } getPayload() { - return serializeToBuffer([this.archive, this.txs]); + return getSignaturePayload(this.archive, this.txs); } toBuffer(): Buffer { diff --git a/yarn-project/circuit-types/src/p2p/block_utils.ts b/yarn-project/circuit-types/src/p2p/block_utils.ts new file mode 100644 index 00000000000..6eca0070a18 --- /dev/null +++ b/yarn-project/circuit-types/src/p2p/block_utils.ts @@ -0,0 +1,32 @@ +import { Buffer32 } from '@aztec/foundation/buffer'; +import { keccak256 as keccak256Buffer } from '@aztec/foundation/crypto'; +import { type Fr } from '@aztec/foundation/fields'; +import { serializeToBuffer } from '@aztec/foundation/serialize'; + +import { keccak256 as keccak2560xString } from 'viem'; + +import { type TxHash } from '../tx/tx_hash.js'; + +/** + * Get the payload for the signature of the block proposal + * @param archive - The archive of the block + * @param txs - The transactions in the block + * @returns The payload for the signature of the block proposal + */ +export function getSignaturePayload(archive: Fr, txs: TxHash[]) { + return serializeToBuffer([archive, Buffer32.fromNumber(txs.length), txs]); +} + +/** + * Get the hashed payload for the signature of the block proposal + * @param archive - The archive of the block + * @param txs - The transactions in the block + * @returns The hashed payload for the signature of the block proposal + */ +export function getHashedSignaturePayload(archive: Fr, txs: TxHash[]): Buffer { + return keccak256Buffer(getSignaturePayload(archive, txs)); +} + +export function get0xStringHashedSignaturePayload(archive: Fr, txs: TxHash[]): `0x${string}` { + return keccak2560xString(getSignaturePayload(archive, txs)); +} diff --git a/yarn-project/circuit-types/src/p2p/index.ts b/yarn-project/circuit-types/src/p2p/index.ts index a8a7f011fd0..e6c268523c1 100644 --- a/yarn-project/circuit-types/src/p2p/index.ts +++ b/yarn-project/circuit-types/src/p2p/index.ts @@ -4,3 +4,4 @@ export * from './interface.js'; export * from './gossipable.js'; export * from './topic_type.js'; export * from './signature.js'; +export * from './block_utils.js'; diff --git a/yarn-project/circuit-types/src/p2p/mocks.ts b/yarn-project/circuit-types/src/p2p/mocks.ts index 0c57accf546..2e4b9495d66 100644 --- a/yarn-project/circuit-types/src/p2p/mocks.ts +++ b/yarn-project/circuit-types/src/p2p/mocks.ts @@ -1,14 +1,13 @@ import { makeHeader } from '@aztec/circuits.js/testing'; import { Fr } from '@aztec/foundation/fields'; -import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type PrivateKeyAccount } from 'viem'; -import { keccak256 } from 'viem'; import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'; import { TxHash } from '../tx/tx_hash.js'; import { BlockAttestation } from './block_attestation.js'; import { BlockProposal } from './block_proposal.js'; +import { get0xStringHashedSignaturePayload } from './block_utils.js'; import { Signature } from './signature.js'; export const makeBlockProposal = async (signer?: PrivateKeyAccount): Promise => { @@ -17,7 +16,7 @@ export const makeBlockProposal = async (signer?: PrivateKeyAccount): Promise TxHash.random()); - const hash = keccak256(serializeToBuffer([archive, txs])); + const hash = get0xStringHashedSignaturePayload(archive, txs); const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } })); return new BlockProposal(blockHeader, archive, txs, signature); @@ -30,7 +29,7 @@ export const makeBlockAttestation = async (signer?: PrivateKeyAccount): Promise< const blockHeader = makeHeader(1); const archive = Fr.random(); const txs = [0, 1, 2, 3, 4, 5].map(() => TxHash.random()); - const hash = keccak256(serializeToBuffer([archive, txs])); + const hash = get0xStringHashedSignaturePayload(archive, txs); const signature = Signature.from0xString(await signer.signMessage({ message: { raw: hash } })); return new BlockAttestation(blockHeader, archive, txs, signature); diff --git a/yarn-project/foundation/src/buffer/buffer32.ts b/yarn-project/foundation/src/buffer/buffer32.ts index 399cdb009e3..736c0ada457 100644 --- a/yarn-project/foundation/src/buffer/buffer32.ts +++ b/yarn-project/foundation/src/buffer/buffer32.ts @@ -116,6 +116,15 @@ export class Buffer32 { return new Buffer32(Buffer.from(str, 'hex')); } + /** + * Converts a number into a Buffer32 object. + * @param num - The number to convert. + * @returns A new Buffer32 object. + */ + public static fromNumber(num: number): Buffer32 { + return new Buffer32(serializeBigInt(BigInt(num), Buffer32.SIZE)); + } + /** * Generates a random Buffer32. * @returns A new Buffer32 object. diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 4c1937a6b79..8930d86b890 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,8 +1,8 @@ import { type L2Block, type Signature, type TxHash } from '@aztec/circuit-types'; +import { getHashedSignaturePayload } from '@aztec/circuit-types'; import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; import { ETHEREUM_SLOT_DURATION, EthAddress, type Header, type Proof } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; -import { keccak256 } from '@aztec/foundation/crypto'; import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { serializeToBuffer } from '@aztec/foundation/serialize'; @@ -255,7 +255,7 @@ export class L1Publisher { blockHash: block.hash().toString(), }; - const digest = keccak256(serializeToBuffer(block.archive.root, txHashes ?? [])); + const digest = getHashedSignaturePayload(block.archive.root, txHashes ?? []); const proposeTxArgs = { header: block.header.toBuffer(), archive: block.archive.root.toBuffer(), diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index 1115d72208f..79e741a4ea6 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -2,7 +2,6 @@ import { BlockAttestation, BlockProposal, type TxHash } from '@aztec/circuit-typ import { type Header } from '@aztec/circuits.js'; import { keccak256 } from '@aztec/foundation/crypto'; import { type Fr } from '@aztec/foundation/fields'; -import { serializeToBuffer } from '@aztec/foundation/serialize'; import { type ValidatorKeyStore } from '../key_store/interface.js'; @@ -19,12 +18,9 @@ export class ValidationService { * @returns A block proposal signing the above information (not the current implementation!!!) */ async createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { - // NOTE: just signing the archive and txs for now - const payload = serializeToBuffer([archive, txs]); - const hashed = keccak256(payload); - const sig = await this.keyStore.sign(hashed); + const payloadSigner = (payload: Buffer) => this.keyStore.sign(payload); - return new BlockProposal(header, archive, txs, sig); + return BlockProposal.createProposalFromSigner(header, archive, txs, payloadSigner); } /** @@ -40,6 +36,7 @@ export class ValidationService { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct const buf = keccak256(proposal.getPayload()); + console.log("attestation buf", buf); const sig = await this.keyStore.sign(buf); return new BlockAttestation(proposal.header, proposal.archive, proposal.txs, sig); } From e6e7f6b2072a8b6d382c41d0a73e2e76c865649d Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:17:37 +0000 Subject: [PATCH 23/26] fix --- yarn-project/circuit-types/src/p2p/block_utils.ts | 10 ++++++---- yarn-project/p2p/src/client/p2p_client.ts | 6 ++++-- yarn-project/p2p/src/service/service.ts | 2 +- .../src/duties/validation_service.ts | 3 +-- yarn-project/validator-client/src/validator.ts | 13 ++++++++++--- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/yarn-project/circuit-types/src/p2p/block_utils.ts b/yarn-project/circuit-types/src/p2p/block_utils.ts index 6eca0070a18..cd1c5a48842 100644 --- a/yarn-project/circuit-types/src/p2p/block_utils.ts +++ b/yarn-project/circuit-types/src/p2p/block_utils.ts @@ -1,9 +1,7 @@ -import { Buffer32 } from '@aztec/foundation/buffer'; import { keccak256 as keccak256Buffer } from '@aztec/foundation/crypto'; import { type Fr } from '@aztec/foundation/fields'; -import { serializeToBuffer } from '@aztec/foundation/serialize'; -import { keccak256 as keccak2560xString } from 'viem'; +import { encodeAbiParameters, keccak256 as keccak2560xString, parseAbiParameters } from 'viem'; import { type TxHash } from '../tx/tx_hash.js'; @@ -14,7 +12,11 @@ import { type TxHash } from '../tx/tx_hash.js'; * @returns The payload for the signature of the block proposal */ export function getSignaturePayload(archive: Fr, txs: TxHash[]) { - return serializeToBuffer([archive, Buffer32.fromNumber(txs.length), txs]); + const abi = parseAbiParameters('bytes32, bytes32[]'); + const txArray = txs.map(tx => tx.to0xString()); + const encodedData = encodeAbiParameters(abi, [archive.toString(), txArray] as const); + + return Buffer.from(encodedData.slice(2), 'hex'); } /** diff --git a/yarn-project/p2p/src/client/p2p_client.ts b/yarn-project/p2p/src/client/p2p_client.ts index 7534c320164..9fec7856fae 100644 --- a/yarn-project/p2p/src/client/p2p_client.ts +++ b/yarn-project/p2p/src/client/p2p_client.ts @@ -70,7 +70,7 @@ export interface P2P { */ // REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963 // ^ This pattern is not my favorite (md) - registerBlockProposalHandler(handler: (block: BlockProposal) => Promise): void; + registerBlockProposalHandler(handler: (block: BlockProposal) => Promise): void; /** * Request a list of transactions from another peer by their tx hashes. @@ -287,7 +287,7 @@ export class P2PClient implements P2P { // REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963 // ^ This pattern is not my favorite (md) - public registerBlockProposalHandler(handler: (block: BlockProposal) => Promise): void { + public registerBlockProposalHandler(handler: (block: BlockProposal) => Promise): void { this.p2pService.registerBlockReceivedCallback(handler); } @@ -319,6 +319,8 @@ export class P2PClient implements P2P { this.log.debug(`Requested ${txHash.toString()} from peer | success = ${!!tx}`); if (tx) { + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8485): This check is not sufficient to validate the transaction. We need to validate the entire proof. + // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8483): alter peer scoring system for a validator that returns an invalid transcation await this.txPool.addTxs([tx]); } diff --git a/yarn-project/p2p/src/service/service.ts b/yarn-project/p2p/src/service/service.ts index 607927d3454..ce486e0b2bb 100644 --- a/yarn-project/p2p/src/service/service.ts +++ b/yarn-project/p2p/src/service/service.ts @@ -46,7 +46,7 @@ export interface P2PService { ): Promise | undefined>; // Leaky abstraction: fix https://github.com/AztecProtocol/aztec-packages/issues/7963 - registerBlockReceivedCallback(callback: (block: BlockProposal) => Promise): void; + registerBlockReceivedCallback(callback: (block: BlockProposal) => Promise): void; getEnr(): ENR | undefined; } diff --git a/yarn-project/validator-client/src/duties/validation_service.ts b/yarn-project/validator-client/src/duties/validation_service.ts index 79e741a4ea6..3a4ec7e8c6d 100644 --- a/yarn-project/validator-client/src/duties/validation_service.ts +++ b/yarn-project/validator-client/src/duties/validation_service.ts @@ -17,7 +17,7 @@ export class ValidationService { * * @returns A block proposal signing the above information (not the current implementation!!!) */ - async createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { + createBlockProposal(header: Header, archive: Fr, txs: TxHash[]): Promise { const payloadSigner = (payload: Buffer) => this.keyStore.sign(payload); return BlockProposal.createProposalFromSigner(header, archive, txs, payloadSigner); @@ -36,7 +36,6 @@ export class ValidationService { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7961): check that the current validator is correct const buf = keccak256(proposal.getPayload()); - console.log("attestation buf", buf); const sig = await this.keyStore.sign(buf); return new BlockAttestation(proposal.header, proposal.archive, proposal.txs, sig); } diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index a4ccd25f6ba..1c8442ef367 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -63,15 +63,22 @@ export class ValidatorClient implements Validator { } public registerBlockProposalHandler() { - const handler = (block: BlockProposal): Promise => { + const handler = (block: BlockProposal): Promise => { return this.attestToProposal(block); }; this.p2pClient.registerBlockProposalHandler(handler); } - async attestToProposal(proposal: BlockProposal): Promise { + async attestToProposal(proposal: BlockProposal): Promise { // Check that all of the tranasctions in the proposal are available in the tx pool before attesting - await this.ensureTransactionsAreAvailable(proposal); + try { + await this.ensureTransactionsAreAvailable(proposal); + } catch (error: any) { + if (error instanceof TransactionsNotAvailableError) { + this.log.error(`Transactions not available, skipping attestation ${error.message}`); + } + return undefined; + } this.log.debug(`Transactions available, attesting to proposal with ${proposal.txs.length} transactions`); // If the above function does not throw an error, then we can attest to the proposal From cde6283c83db0efbf3b9d2b37b6adf8f377b3105 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:09:53 +0000 Subject: [PATCH 24/26] fix: merge fix --- .../src/composed/integration_l1_publisher.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index bc59c817ebc..ea3b881330f 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -427,12 +427,13 @@ describe('L1Publisher integration', () => { const expectedData = encodeFunctionData({ abi: RollupAbi, - functionName: 'propose', + functionName: 'proposeWithBody', args: [ `0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, [], + [], `0x${block.body.toBuffer().toString('hex')}`, ], }); @@ -530,12 +531,13 @@ describe('L1Publisher integration', () => { i == 0 ? encodeFunctionData({ abi: RollupAbi, - functionName: 'propose', + functionName: 'proposeWithBody', args: [ `0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, [], + [], `0x${block.body.toBuffer().toString('hex')}`, ], }) @@ -547,6 +549,7 @@ describe('L1Publisher integration', () => { `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, [], + [] ], }); expect(ethTx.input).toEqual(expectedData); From 8290c99a5d01119ca819941067d3e6a6d046ea77 Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:10:50 +0000 Subject: [PATCH 25/26] fmt --- .../end-to-end/src/composed/integration_l1_publisher.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index ea3b881330f..89041117a11 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -549,7 +549,7 @@ describe('L1Publisher integration', () => { `0x${block.archive.root.toBuffer().toString('hex')}`, `0x${block.header.hash().toBuffer().toString('hex')}`, [], - [] + [], ], }); expect(ethTx.input).toEqual(expectedData); From b2ee826d83c0e2b1062a160c58a7ea641d4d6cbe Mon Sep 17 00:00:00 2001 From: Maddiaa0 <47148561+Maddiaa0@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:05:03 +0000 Subject: [PATCH 26/26] fix --- .../p2p/src/attestation_pool/memory_attestation_pool.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts b/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts index 21a10391f13..4503d287fa1 100644 --- a/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts +++ b/yarn-project/p2p/src/attestation_pool/memory_attestation_pool.test.ts @@ -21,7 +21,6 @@ describe('MemoryAttestationPool', () => { const archive = Fr.random(); const attestations = await Promise.all(signers.map(signer => mockAttestation(signer, slotNumber, archive))); - // TODO(md): this will change across the board const proposalId = attestations[0].p2pMessageIdentifier.toString(); await ap.addAttestations(attestations);