From 9d7e06220930e5d78072189b22d35f06d4ffb4c2 Mon Sep 17 00:00:00 2001 From: LHerskind Date: Fri, 2 Aug 2024 21:35:23 +0000 Subject: [PATCH] feat: constraining slots --- l1-contracts/src/core/Rollup.sol | 334 ++++++++++++++---- l1-contracts/src/core/interfaces/IRollup.sol | 25 +- .../src/core/libraries/ConstantsGen.sol | 1 + l1-contracts/src/core/libraries/Errors.sol | 9 +- l1-contracts/src/core/libraries/HeaderLib.sol | 48 --- .../core/sequencer_selection/ILeonidas.sol | 4 + .../src/core/sequencer_selection/Leonidas.sol | 132 ++++++- l1-contracts/test/Rollup.t.sol | 72 ++-- l1-contracts/test/fixtures/empty_block_1.json | 14 +- l1-contracts/test/fixtures/empty_block_2.json | 16 +- l1-contracts/test/fixtures/mixed_block_1.json | 14 +- l1-contracts/test/fixtures/mixed_block_2.json | 16 +- l1-contracts/test/sparta/Sparta.t.sol | 85 +++-- .../crates/types/src/constants.nr | 1 + .../archiver/src/archiver/eth_log_handlers.ts | 57 ++- .../aztec.js/src/utils/cheat_codes.ts | 41 ++- yarn-project/circuits.js/src/constants.gen.ts | 1 + .../composed/integration_l1_publisher.test.ts | 80 ++++- .../end-to-end/src/e2e_cheat_codes.test.ts | 55 +-- .../src/e2e_crowdfunding_and_claim.test.ts | 2 +- .../src/e2e_lending_contract.test.ts | 35 +- .../src/guides/dapp_testing.test.ts | 23 -- .../src/simulators/lending_simulator.ts | 30 +- .../ethereum/src/deploy_l1_contracts.ts | 19 + .../src/orchestrator/orchestrator.ts | 4 +- .../global_variable_builder/global_builder.ts | 61 ++-- .../global_variable_builder/viem-reader.ts | 16 +- .../src/publisher/l1-publisher.test.ts | 70 ++-- .../src/publisher/l1-publisher.ts | 77 ++-- .../src/publisher/viem-tx-sender.ts | 33 +- .../src/sequencer/sequencer.test.ts | 194 ++++------ .../src/sequencer/sequencer.ts | 4 + 32 files changed, 986 insertions(+), 587 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 7d73451658a..027afbaa2c6 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.18; // Interfaces -import {IRollup} from "./interfaces/IRollup.sol"; +import {IRollup, ITestRollup} from "./interfaces/IRollup.sol"; import {IAvailabilityOracle} from "./interfaces/IAvailabilityOracle.sol"; import {IInbox} from "./interfaces/messagebridge/IInbox.sol"; import {IOutbox} from "./interfaces/messagebridge/IOutbox.sol"; @@ -13,7 +13,6 @@ import {IERC20} from "@oz/token/ERC20/IERC20.sol"; // Libraries import {HeaderLib} from "./libraries/HeaderLib.sol"; -import {Hash} from "./libraries/Hash.sol"; import {Errors} from "./libraries/Errors.sol"; import {Constants} from "./libraries/ConstantsGen.sol"; import {MerkleLib} from "./libraries/MerkleLib.sol"; @@ -31,9 +30,10 @@ import {Leonidas} from "./sequencer_selection/Leonidas.sol"; * @notice Rollup contract that is concerned about readability and velocity of development * not giving a damn about gas costs. */ -contract Rollup is Leonidas, IRollup { +contract Rollup is Leonidas, IRollup, ITestRollup { struct BlockLog { bytes32 archive; + uint128 slotNumber; bool isProven; } @@ -46,11 +46,6 @@ contract Rollup is Leonidas, IRollup { IVerifier public verifier; - uint256 public lastBlockTs; - // Tracks the last time time was warped on L2 ("warp" is the testing cheatcode). - // See https://github.com/AztecProtocol/aztec-packages/issues/1614 - uint256 public lastWarpedBlockTs; - uint256 public pendingBlockCount; uint256 public provenBlockCount; @@ -63,6 +58,10 @@ contract Rollup is Leonidas, IRollup { bytes32 public vkTreeRoot; + // @note This should not exists, but we have it now to ensure we will not be killing the devnet with our + // timeliness requirements. + bool public isDevNet = false; + constructor( IRegistry _registry, IAvailabilityOracle _availabilityOracle, @@ -79,88 +78,78 @@ contract Rollup is Leonidas, IRollup { VERSION = 1; // Genesis block - blocks[0] = BlockLog(bytes32(0), true); + blocks[0] = BlockLog({archive: bytes32(0), slotNumber: 0, isProven: true}); pendingBlockCount = 1; provenBlockCount = 1; } - function setVerifier(address _verifier) external override(IRollup) { - // TODO remove, only needed for testing - verifier = IVerifier(_verifier); - } - - function setVkTreeRoot(bytes32 _vkTreeRoot) external { - vkTreeRoot = _vkTreeRoot; - } - - function archive() public view returns (bytes32) { - return blocks[pendingBlockCount - 1].archive; + /** + * @notice Set the devnet mode + * + * @dev This is only needed for testing, and should be removed + * + * @param _devNet - Whether or not the contract is in devnet mode + */ + function setDevNet(bool _devNet) external override(ITestRollup) { + isDevNet = _devNet; } - function isBlockProven(uint256 _blockNumber) public view returns (bool) { - return blocks[_blockNumber].isProven; + /** + * @notice Set the verifier contract + * + * @dev This is only needed for testing, and should be removed + * + * @param _verifier - The new verifier contract + */ + function setVerifier(address _verifier) external override(ITestRollup) { + verifier = IVerifier(_verifier); } - function archiveAt(uint256 _blockNumber) public view returns (bytes32) { - return blocks[_blockNumber].archive; + /** + * @notice Set the vkTreeRoot + * + * @dev This is only needed for testing, and should be removed + * + * @param _vkTreeRoot - The new vkTreeRoot to be used by proofs + */ + function setVkTreeRoot(bytes32 _vkTreeRoot) external override(ITestRollup) { + vkTreeRoot = _vkTreeRoot; } /** - * @notice Process an incoming L2 block and progress the state + * @notice Published the body and processes the block + * @dev This should likely be purged in the future as it is a convenience method + * @dev `eth_log_handlers` rely on this function + * * @param _header - The L2 block header * @param _archive - A root of the archive tree after the L2 block is applied * @param _signatures - Signatures from the validators + * @param _body - The body of the L2 block */ - function process( + function publishAndProcess( bytes calldata _header, bytes32 _archive, - SignatureLib.Signature[] memory _signatures - ) public { - _processPendingBlock(_signatures, _archive); - - // Decode and validate header - HeaderLib.Header memory header = HeaderLib.decode(_header); - HeaderLib.validate(header, VERSION, getCurrentSlot(), lastBlockTs, archive()); - - if (header.globalVariables.blockNumber != pendingBlockCount) { - revert Errors.Rollup__InvalidBlockNumber( - pendingBlockCount, header.globalVariables.blockNumber - ); - } - - // 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)) { - revert Errors.Rollup__UnavailableTxs(header.contentCommitment.txsEffectsHash); - } - - blocks[pendingBlockCount++] = BlockLog(_archive, false); - - lastBlockTs = block.timestamp; - - bytes32 inHash = INBOX.consume(); - if (header.contentCommitment.inHash != inHash) { - revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); - } - - // TODO(#7218): Revert to fixed height tree for outbox, currently just providing min as interim - // Min size = smallest path of the rollup tree + 1 - (uint256 min,) = MerkleLib.computeMinMaxPathLength(header.contentCommitment.numTxs); - uint256 l2ToL1TreeMinHeight = min + 1; - OUTBOX.insert( - header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight - ); - - // pay the coinbase 1 gas token if it is not empty and header.totalFees is not zero - if (header.globalVariables.coinbase != address(0) && header.totalFees > 0) { - GAS_TOKEN.transfer(address(header.globalVariables.coinbase), header.totalFees); - } - - emit L2BlockProcessed(header.globalVariables.blockNumber); + SignatureLib.Signature[] memory _signatures, + bytes calldata _body + ) external override(IRollup) { + AVAILABILITY_ORACLE.publish(_body); + process(_header, _archive, _signatures); } - function process(bytes calldata _header, bytes32 _archive) external override(IRollup) { - SignatureLib.Signature[] memory emptySignatures = new SignatureLib.Signature[](0); - process(_header, _archive, emptySignatures); + /** + * @notice Published the body and processes the block + * @dev This should likely be purged in the future as it is a convenience method + * @dev `eth_log_handlers` rely on this function + * @param _header - The L2 block header + * @param _archive - A root of the archive tree after the L2 block is applied + * @param _body - The body of the L2 block + */ + function publishAndProcess(bytes calldata _header, bytes32 _archive, bytes calldata _body) + external + override(IRollup) + { + AVAILABILITY_ORACLE.publish(_body); + process(_header, _archive); } /** @@ -201,14 +190,13 @@ contract Rollup is Leonidas, IRollup { } bytes32 expectedLastArchive = blocks[header.globalVariables.blockNumber - 1].archive; - bytes32 expectedArchive = blocks[header.globalVariables.blockNumber].archive; - // We do it this way to provide better error messages than passing along the storage values // TODO(#4148) Proper genesis state. If the state is empty, we allow anything for now. if (expectedLastArchive != bytes32(0) && header.lastArchive.root != expectedLastArchive) { revert Errors.Rollup__InvalidArchive(expectedLastArchive, header.lastArchive.root); } + bytes32 expectedArchive = blocks[header.globalVariables.blockNumber].archive; if (_archive != expectedArchive) { revert Errors.Rollup__InvalidProposedArchive(expectedArchive, _archive); } @@ -254,6 +242,95 @@ contract Rollup is Leonidas, IRollup { emit L2ProofVerified(header.globalVariables.blockNumber, _proverId); } + /** + * @notice Get the `isProven` flag for the block number + * + * @param _blockNumber - The block number to check + * + * @return bool - True if proven, false otherwise + */ + function isBlockProven(uint256 _blockNumber) external view override(IRollup) returns (bool) { + return blocks[_blockNumber].isProven; + } + + /** + * @notice Get the archive root of a specific block + * + * @param _blockNumber - The block number to get the archive root of + * + * @return bytes32 - The archive root of the block + */ + function archiveAt(uint256 _blockNumber) external view override(IRollup) returns (bytes32) { + return blocks[_blockNumber].archive; + } + + /** + * @notice Processes an incoming L2 block with signatures + * + * @param _header - The L2 block header + * @param _archive - A root of the archive tree after the L2 block is applied + * @param _signatures - Signatures from the validators + */ + function process( + bytes calldata _header, + bytes32 _archive, + SignatureLib.Signature[] memory _signatures + ) public override(IRollup) { + // Decode and validate header + HeaderLib.Header memory header = HeaderLib.decode(_header); + _validateHeaderForSubmissionBase(header); + _validateHeaderForSubmissionSequencerSelection(header, _signatures, _archive); + + // 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, + slotNumber: uint128(header.globalVariables.slotNumber), + isProven: false + }); + + bytes32 inHash = INBOX.consume(); + if (header.contentCommitment.inHash != inHash) { + revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); + } + + // TODO(#7218): Revert to fixed height tree for outbox, currently just providing min as interim + // Min size = smallest path of the rollup tree + 1 + (uint256 min,) = MerkleLib.computeMinMaxPathLength(header.contentCommitment.numTxs); + uint256 l2ToL1TreeMinHeight = min + 1; + OUTBOX.insert( + header.globalVariables.blockNumber, header.contentCommitment.outHash, l2ToL1TreeMinHeight + ); + + // @todo This should be address at time of proving. Also, this contract should NOT have funds!!! + // pay the coinbase 1 gas token if it is not empty and header.totalFees is not zero + if (header.globalVariables.coinbase != address(0) && header.totalFees > 0) { + GAS_TOKEN.transfer(address(header.globalVariables.coinbase), header.totalFees); + } + + emit L2BlockProcessed(header.globalVariables.blockNumber); + } + + /** + * @notice Processes an incoming L2 block without signatures + * + * @param _header - The L2 block header + * @param _archive - A root of the archive tree after the L2 block is applied + */ + function process(bytes calldata _header, bytes32 _archive) public override(IRollup) { + SignatureLib.Signature[] memory emptySignatures = new SignatureLib.Signature[](0); + process(_header, _archive, emptySignatures); + } + + /** + * @notice Get the current archive root + * + * @return bytes32 - The current archive root + */ + function archive() public view override(IRollup) returns (bytes32) { + return blocks[pendingBlockCount - 1].archive; + } + /** * @notice Progresses the state of the proven chain as far as possible * @@ -284,4 +361,115 @@ contract Rollup is Leonidas, IRollup { emit ProgressedState(provenBlockCount, pendingBlockCount); } } + + /** + * @notice Validate a header for submission to the pending chain (sequencer selection checks) + * + * These validation checks are directly related to Leonidas. + * Note that while these checks are strict, they can be relaxed with some changes to + * message boxes. + * + * Each of the following validation checks must pass, otherwise an error is thrown and we revert. + * - The slot MUST be the current slot + * This might be relaxed for allow consensus set to better handle short-term bursts of L1 congestion + * - The slot MUST be in the current epoch + * + * @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 _signatures - The signatures to validate + * @param _archive - The archive root of the block + */ + function _validateHeaderForSubmissionSequencerSelection( + HeaderLib.Header memory _header, + SignatureLib.Signature[] memory _signatures, + bytes32 _archive + ) internal { + if (isDevNet) { + if (!isValidator(msg.sender)) { + revert Errors.Leonidas__InvalidProposer(address(0), 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); + } + + // @note We are currently enforcing that the slot is in the current epoch + // If this is not the case, there could potentially be a weird reorg + // 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(); + if (epochNumber != currentEpoch) { + revert Errors.Rollup__InvalidEpoch(currentEpoch, epochNumber); + } + + _processPendingBlock(epochNumber, slot, _signatures, _archive); + } + + /** + * @notice Validate a header for submission to the pending chain (base checks) + * Base checks here being the checks that we wish to do regardless of the sequencer + * selection mechanism. + * + * Each of the following validation checks must pass, otherwise an error is thrown and we revert. + * - The chain ID MUST match the current chain ID + * - The version MUST match the current version + * - The block id MUST be the next block in the chain + * - The last archive root in the header MUST match the current archive + * - The slot MUST be larger than the slot of the previous block (ensures single block per slot) + * - The timestamp MUST be equal to GENESIS_TIME + slot * SLOT_DURATION + * - The availability oracle MUST return true for availability of txsEffectsHash + * - This can be relaxed to happen at the time of `submitProof` instead + * + * @param _header - The header to validate + */ + function _validateHeaderForSubmissionBase(HeaderLib.Header memory _header) internal view { + if (block.chainid != _header.globalVariables.chainId) { + revert Errors.Rollup__InvalidChainId(block.chainid, _header.globalVariables.chainId); + } + + if (_header.globalVariables.version != VERSION) { + revert Errors.Rollup__InvalidVersion(VERSION, _header.globalVariables.version); + } + + if (_header.globalVariables.blockNumber != pendingBlockCount) { + revert Errors.Rollup__InvalidBlockNumber( + pendingBlockCount, _header.globalVariables.blockNumber + ); + } + + // TODO(#4148) Proper genesis state. If the state is empty, we allow anything for now. + bytes32 tipArchive = archive(); + if (tipArchive != bytes32(0) && tipArchive != _header.lastArchive.root) { + revert Errors.Rollup__InvalidArchive(tipArchive, _header.lastArchive.root); + } + + uint256 slot = _header.globalVariables.slotNumber; + if (slot > type(uint128).max) { + revert Errors.Rollup__SlotValueTooLarge(slot); + } + + uint256 lastSlot = uint256(blocks[pendingBlockCount - 1].slotNumber); + if (slot <= lastSlot) { + revert Errors.Rollup__SlotAlreadyInChain(lastSlot, slot); + } + + uint256 timestamp = getTimestampForSlot(slot); + if (_header.globalVariables.timestamp != timestamp) { + revert Errors.Rollup__InvalidTimestamp(timestamp, _header.globalVariables.timestamp); + } + + // 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)) { + revert Errors.Rollup__UnavailableTxs(_header.contentCommitment.txsEffectsHash); + } + } } diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index 5186bf993cf..a8a9eb947bd 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -2,12 +2,33 @@ // Copyright 2023 Aztec Labs. pragma solidity >=0.8.18; +import {SignatureLib} from "../sequencer_selection/SignatureLib.sol"; + +interface ITestRollup { + function setDevNet(bool _devNet) external; + function setVerifier(address _verifier) external; + function setVkTreeRoot(bytes32 _vkTreeRoot) external; +} + interface IRollup { event L2BlockProcessed(uint256 indexed blockNumber); event L2ProofVerified(uint256 indexed blockNumber, bytes32 indexed proverId); event ProgressedState(uint256 provenBlockCount, uint256 pendingBlockCount); + function publishAndProcess( + bytes calldata _header, + bytes32 _archive, + SignatureLib.Signature[] memory _signatures, + bytes calldata _body + ) external; + function publishAndProcess(bytes calldata _header, bytes32 _archive, bytes calldata _body) + external; function process(bytes calldata _header, bytes32 _archive) external; + function process( + bytes calldata _header, + bytes32 _archive, + SignatureLib.Signature[] memory _signatures + ) external; function submitProof( bytes calldata _header, @@ -17,5 +38,7 @@ interface IRollup { bytes calldata _proof ) external; - function setVerifier(address _verifier) external; + function archive() external view returns (bytes32); + function isBlockProven(uint256 _blockNumber) external view returns (bool); + function archiveAt(uint256 _blockNumber) external view returns (bytes32); } diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 7712289a790..ab33b0b252d 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -91,6 +91,7 @@ library Constants { uint256 internal constant BASE_ROLLUP_INDEX = 20; uint256 internal constant MERGE_ROLLUP_INDEX = 21; uint256 internal constant ROOT_ROLLUP_INDEX = 22; + uint256 internal constant ETHEREUM_SLOT_DURATION = 12; uint256 internal constant FUNCTION_SELECTOR_NUM_BYTES = 4; uint256 internal constant ARGS_HASH_CHUNK_LENGTH = 16; uint256 internal constant ARGS_HASH_CHUNK_COUNT = 16; diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index ce8c5723b65..6382b7ac06f 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -41,11 +41,15 @@ library Errors { error Rollup__InvalidArchive(bytes32 expected, bytes32 actual); // 0xb682a40e error Rollup__InvalidProposedArchive(bytes32 expected, bytes32 actual); // 0x32532e73 error Rollup__InvalidBlockNumber(uint256 expected, uint256 actual); // 0xe5edf847 + error Rollup__SlotValueTooLarge(uint256 slot); // 0x7234f4fe + error Rollup__SlotAlreadyInChain(uint256 lastSlot, uint256 proposedSlot); // 0x83510bd0 + error Rollup__InvalidEpoch(uint256 expected, uint256 actual); // 0x3c6d65e6 error Rollup__TryingToProveNonExistingBlock(); // 0x34ef4954 error Rollup__InvalidInHash(bytes32 expected, bytes32 actual); // 0xcd6f4233 error Rollup__InvalidProof(); // 0xa5b2ba17 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__TimestampTooOld(); // 0x72ed9c81 error Rollup__UnavailableTxs(bytes32 txsHash); // 0x414906c3 @@ -60,6 +64,7 @@ library Errors { // HeaderLib error HeaderLib__InvalidHeaderSize(uint256 expected, uint256 actual); // 0xf3ccb247 + error HeaderLib__InvalidSlotNumber(uint256 expected, uint256 actual); // 0x09ba91ff // MerkleLib error MerkleLib__InvalidRoot(bytes32 expected, bytes32 actual, bytes32 leaf, uint256 leafIndex); // 0x5f216bf1 @@ -72,8 +77,8 @@ library Errors { error SampleLib__IndexOutOfBounds(uint256 requested, uint256 bound); // 0xa12fc559 // Sequencer Selection (Leonidas) - error Leonidas__NotGod(); // 0xabc2f815 error Leonidas__EpochNotSetup(); // 0xcf4e597e error Leonidas__InvalidProposer(address expected, address actual); // 0xd02d278e - error Leonidas__InsufficientAttestations(uint256 expected, uint256 actual); // 0xbf1ca4cb + error Leonidas__InsufficientAttestations(uint256 minimumNeeded, uint256 provided); // 0xbf1ca4cb + error Leonidas__InsufficientAttestationsProvided(uint256 minimumNeeded, uint256 provided); // 0x2e7debe9 } diff --git a/l1-contracts/src/core/libraries/HeaderLib.sol b/l1-contracts/src/core/libraries/HeaderLib.sol index da8eb11c6fc..47a222bf86a 100644 --- a/l1-contracts/src/core/libraries/HeaderLib.sol +++ b/l1-contracts/src/core/libraries/HeaderLib.sol @@ -5,7 +5,6 @@ pragma solidity >=0.8.18; // Libraries import {Errors} from "./Errors.sol"; import {Constants} from "./ConstantsGen.sol"; -import {Hash} from "./Hash.sol"; /** * @title Header Library @@ -108,53 +107,6 @@ library HeaderLib { uint256 private constant HEADER_LENGTH = 0x268; // Header byte length - /** - * @notice Validates the header - * @param _header - The decoded header - * @param _version - The expected version - * @param _slot - The expected slot number - * @dev @todo currently unused, but must be constrained and used to - * constrain the timestamp instead of `lastBlockTs` - * @param _lastBlockTs - The timestamp of the last block - * @param _archive - The expected archive root - */ - function validate( - Header memory _header, - uint256 _version, - uint256 _slot, - uint256 _lastBlockTs, - bytes32 _archive - ) internal view { - if (block.chainid != _header.globalVariables.chainId) { - revert Errors.Rollup__InvalidChainId(block.chainid, _header.globalVariables.chainId); - } - - if (_header.globalVariables.version != _version) { - revert Errors.Rollup__InvalidVersion(_version, _header.globalVariables.version); - } - - // block number already constrained by archive root check - - // @todo Constrain slot number + update timestamp to be linked to slot number - - if (_header.globalVariables.timestamp > block.timestamp) { - revert Errors.Rollup__TimestampInFuture(); - } - - // @todo @LHerskind consider if this is too strict - // This will make multiple l2 blocks in the same l1 block impractical. - // e.g., the first block will update timestamp which will make the second fail. - // Could possibly allow multiple blocks if in same l1 block - if (_header.globalVariables.timestamp < _lastBlockTs) { - revert Errors.Rollup__TimestampTooOld(); - } - - // TODO(#4148) Proper genesis state. If the state is empty, we allow anything for now. - if (_archive != bytes32(0) && _archive != _header.lastArchive.root) { - revert Errors.Rollup__InvalidArchive(_archive, _header.lastArchive.root); - } - } - /** * @notice Decodes the header * @param _header - The header calldata diff --git a/l1-contracts/src/core/sequencer_selection/ILeonidas.sol b/l1-contracts/src/core/sequencer_selection/ILeonidas.sol index bf06ac2f5fd..c77cfdee097 100644 --- a/l1-contracts/src/core/sequencer_selection/ILeonidas.sol +++ b/l1-contracts/src/core/sequencer_selection/ILeonidas.sol @@ -10,12 +10,16 @@ interface ILeonidas { // Likely changing to optimize in Pleistarchus function setupEpoch() external; function getCurrentProposer() external view returns (address); + function getProposerAt(uint256 _ts) external view returns (address); // Stable function getCurrentEpoch() external view returns (uint256); function getCurrentSlot() external view returns (uint256); + function isValidator(address _validator) external view returns (bool); // Consider removing below this point + function getTimestampForSlot(uint256 _slotNumber) external view returns (uint256); + // Likely removal of these to replace with a size and indiviual getter function getEpochCommittee(uint256 _epoch) external view returns (address[] memory); function getValidators() external view returns (address[] memory); diff --git a/l1-contracts/src/core/sequencer_selection/Leonidas.sol b/l1-contracts/src/core/sequencer_selection/Leonidas.sol index 44475c3235a..d7bbbf066bb 100644 --- a/l1-contracts/src/core/sequencer_selection/Leonidas.sol +++ b/l1-contracts/src/core/sequencer_selection/Leonidas.sol @@ -7,6 +7,7 @@ import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol"; import {Ownable} from "@oz/access/Ownable.sol"; import {SignatureLib} from "./SignatureLib.sol"; import {SampleLib} from "./SampleLib.sol"; +import {Constants} from "../libraries/ConstantsGen.sol"; import {ILeonidas} from "./ILeonidas.sol"; @@ -40,13 +41,22 @@ contract Leonidas is Ownable, ILeonidas { uint256 nextSeed; } - // The size/duration of a slot in seconds, multiple of 12 to align with Ethereum blocks - uint256 public constant SLOT_DURATION = 12 * 5; - - // The size/duration of an epoch in slots + // @note @LHerskind - The multiple cause pain and suffering in the E2E tests as we introduce + // a timeliness requirement into the publication that did not exists before, + // and at the same time have a setup that will impact the time at every tx + // because of auto-mine. By using just 1, we can make our test work + // but anything using an actual working chain would eat dung as simulating + // transactions is slower than an actual ethereum slot. + // + // The value should be a higher multiple for any actual chain + uint256 public constant SLOT_DURATION = Constants.ETHEREUM_SLOT_DURATION * 1; + + // The duration of an epoch in slots + // @todo @LHerskind - This value should be updated when we are not blind. uint256 public constant EPOCH_DURATION = 32; // The target number of validators in a committee + // @todo @LHerskind - This value should be updated when we are not blind. uint256 public constant TARGET_COMMITTEE_SIZE = EPOCH_DURATION; // The time that the contract was deployed @@ -59,7 +69,7 @@ contract Leonidas is Ownable, ILeonidas { mapping(uint256 epochNumber => Epoch epoch) public epochs; // The last stored randao value, same value as `seed` in the last inserted epoch - uint256 internal lastSeed; + uint256 private lastSeed; constructor(address _ares) Ownable(_ares) { GENESIS_TIME = block.timestamp; @@ -129,6 +139,17 @@ contract Leonidas is Ownable, ILeonidas { return validatorSet.values(); } + /** + * @notice Checks if an address is in the validator set + * + * @param _validator - The address to check + * + * @return True if the address is in the validator set, false otherwise + */ + function isValidator(address _validator) public view override(ILeonidas) returns (bool) { + return validatorSet.contains(_validator); + } + /** * @notice Performs a setup of an epoch if needed. The setup will * - Sample the validator set for the epoch @@ -158,7 +179,7 @@ contract Leonidas is Ownable, ILeonidas { * @return The current epoch number */ function getCurrentEpoch() public view override(ILeonidas) returns (uint256) { - return (block.timestamp - GENESIS_TIME) / (EPOCH_DURATION * SLOT_DURATION); + return getEpochAt(block.timestamp); } /** @@ -167,12 +188,45 @@ contract Leonidas is Ownable, ILeonidas { * @return The current slot number */ function getCurrentSlot() public view override(ILeonidas) returns (uint256) { - return (block.timestamp - GENESIS_TIME) / SLOT_DURATION; + return getSlotAt(block.timestamp); + } + + /** + * @notice Get the timestamp for a given slot + * + * @param _slotNumber - The slot number to get the timestamp for + * + * @return The timestamp for the given slot + */ + function getTimestampForSlot(uint256 _slotNumber) + public + view + override(ILeonidas) + returns (uint256) + { + return _slotNumber * SLOT_DURATION + GENESIS_TIME; } /** * @notice Get the proposer for the current slot * + * @dev Calls `getCurrentProposer(uint256)` with the current timestamp + * + * @return The address of the proposer + */ + function getCurrentProposer() public view override(ILeonidas) returns (address) { + return getProposerAt(block.timestamp); + } + + /** + * @notice Get the proposer for the slot at a specific timestamp + * + * @dev This function is very useful for off-chain usage, as it easily allow a client to + * determine who will be the proposer at the NEXT ethereum block. + * Should not be trusted when moving beyond the current epoch, since changes to the + * validator set might not be reflected when we actually reach that epoch (more changes + * might have happened). + * * @dev The proposer is selected from the validator set of the current epoch. * * @dev Should only be access on-chain if epoch is setup, otherwise very expensive. @@ -185,12 +239,12 @@ contract Leonidas is Ownable, ILeonidas { * * @return The address of the proposer */ - function getCurrentProposer() public view override(ILeonidas) returns (address) { - uint256 epochNumber = getCurrentEpoch(); + function getProposerAt(uint256 _ts) public view override(ILeonidas) returns (address) { + uint256 epochNumber = getEpochAt(_ts); + uint256 slot = getSlotAt(_ts); if (epochNumber == 0) { return address(0); } - uint256 slot = getCurrentSlot(); Epoch storage epoch = epochs[epochNumber]; @@ -219,28 +273,38 @@ contract Leonidas is Ownable, ILeonidas { /** * @notice Process a pending block from the point-of-view of sequencer selection. Will: * - Setup the epoch if needed (if epoch committee is empty skips the rest) - * - Validate that the proposer is the current proposer + * - Validate that the proposer is the proposer of the slot * - Validate that the signatures for attestations are indeed from the validatorset * - Validate that the number of valid attestations is sufficient * * @dev Cases where errors are thrown: * - If the epoch is not setup - * - If the proposer is not the current proposer + * - 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(SignatureLib.Signature[] memory _signatures, bytes32 _digest) - internal - { + 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[getCurrentEpoch()]; + Epoch storage epoch = epochs[_epochNumber]; // We should never enter this case because of `setupEpoch` if (epoch.sampleSeed == 0) { revert Errors.Leonidas__EpochNotSetup(); } - address proposer = getCurrentProposer(); + address proposer = getProposerAt(getTimestampForSlot(_slot)); // If the proposer is open, we allow anyone to propose without needing any signatures if (proposer == address(0)) { @@ -252,8 +316,14 @@ contract Leonidas is Ownable, ILeonidas { revert Errors.Leonidas__InvalidProposer(proposer, msg.sender); } + uint256 needed = epoch.committee.length * 2 / 3 + 1; + if (_signatures.length < needed) { + revert Errors.Leonidas__InsufficientAttestationsProvided(needed, _signatures.length); + } + // Validate the attestations uint256 validAttestations = 0; + for (uint256 i = 0; i < _signatures.length; i++) { SignatureLib.Signature memory signature = _signatures[i]; if (signature.isEmpty) { @@ -264,7 +334,7 @@ contract Leonidas is Ownable, ILeonidas { signature.verify(epoch.committee[i], _digest); validAttestations++; } - uint256 needed = epoch.committee.length * 2 / 3 + 1; + if (validAttestations < needed) { revert Errors.Leonidas__InsufficientAttestations(needed, validAttestations); } @@ -316,6 +386,10 @@ contract Leonidas is Ownable, ILeonidas { /** * @notice Get the sample seed for an epoch * + * @dev This should behave as walking past the line, but it does not currently do that. + * If there are entire skips, e.g., 1, 2, 5 and we then go back and try executing + * for 4 we will get an invalid value because we will read lastSeed which is from 5. + * * @dev The `_epoch` will never be 0 nor in the future * * @dev The return value will be equal to keccak256(n, block.prevrandao) for n being the last epoch @@ -337,6 +411,28 @@ contract Leonidas is Ownable, ILeonidas { return lastSeed; } + /** + * @notice Computes the epoch at a specific time + * + * @param _ts - The timestamp to compute the epoch for + * + * @return The computed epoch + */ + function getEpochAt(uint256 _ts) public view returns (uint256) { + return (_ts - GENESIS_TIME) / (EPOCH_DURATION * SLOT_DURATION); + } + + /** + * @notice Computes the slot at a specific time + * + * @param _ts - The timestamp to compute the slot for + * + * @return The computed slot + */ + function getSlotAt(uint256 _ts) public view returns (uint256) { + return (_ts - GENESIS_TIME) / SLOT_DURATION; + } + /** * @notice Computes the nextSeed for an epoch * diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index eb95eeb1d29..40db2e9cbb7 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -14,6 +14,7 @@ import {Inbox} from "../src/core/messagebridge/Inbox.sol"; import {Outbox} from "../src/core/messagebridge/Outbox.sol"; import {Errors} from "../src/core/libraries/Errors.sol"; import {Rollup} from "../src/core/Rollup.sol"; +import {Leonidas} from "../src/core/sequencer_selection/Leonidas.sol"; import {AvailabilityOracle} from "../src/core/availability_oracle/AvailabilityOracle.sol"; import {NaiveMerkle} from "./merkle/Naive.sol"; import {MerkleTestUtil} from "./merkle/TestUtil.sol"; @@ -36,7 +37,19 @@ contract RollupTest is DecoderBase { AvailabilityOracle internal availabilityOracle; - function setUp() public virtual { + /** + * @notice Set up the contracts needed for the tests with time aligned to the provided block name + */ + modifier setUpFor(string memory _name) { + { + Leonidas leo = new Leonidas(address(1)); + DecoderBase.Full memory full = load(_name); + uint256 slotNumber = full.block.decodedHeader.globalVariables.slotNumber; + uint256 initialTime = + full.block.decodedHeader.globalVariables.timestamp - slotNumber * leo.SLOT_DURATION(); + vm.warp(initialTime); + } + registry = new Registry(); availabilityOracle = new AvailabilityOracle(); portalERC20 = new PortalERC20(); @@ -51,16 +64,17 @@ contract RollupTest is DecoderBase { merkleTestUtil = new MerkleTestUtil(); txsHelper = new TxsDecoderHelper(); + _; } - function testMixedBlock(bool _toProve) public { + function testMixedBlock(bool _toProve) public setUpFor("mixed_block_1") { _testBlock("mixed_block_1", _toProve); assertEq(rollup.pendingBlockCount(), 2, "Invalid pending block count"); assertEq(rollup.provenBlockCount(), _toProve ? 2 : 1, "Invalid proven block count"); } - function testConsecutiveMixedBlocks(uint256 _blocksToProve) public { + function testConsecutiveMixedBlocks(uint256 _blocksToProve) public setUpFor("mixed_block_1") { uint256 toProve = bound(_blocksToProve, 0, 2); _testBlock("mixed_block_1", toProve > 0); @@ -70,7 +84,7 @@ contract RollupTest is DecoderBase { assertEq(rollup.provenBlockCount(), 1 + toProve, "Invalid proven block count"); } - function testConsecutiveMixedBlocksNonSequentialProof() public { + function testConsecutiveMixedBlocksNonSequentialProof() public setUpFor("mixed_block_1") { _testBlock("mixed_block_1", false); _testBlock("mixed_block_2", true); @@ -80,13 +94,13 @@ contract RollupTest is DecoderBase { assertEq(rollup.provenBlockCount(), 1, "Invalid proven block count"); } - function testEmptyBlock(bool _toProve) public { + function testEmptyBlock(bool _toProve) public setUpFor("empty_block_1") { _testBlock("empty_block_1", _toProve); assertEq(rollup.pendingBlockCount(), 2, "Invalid pending block count"); assertEq(rollup.provenBlockCount(), _toProve ? 2 : 1, "Invalid proven block count"); } - function testConsecutiveEmptyBlocks(uint256 _blocksToProve) public { + function testConsecutiveEmptyBlocks(uint256 _blocksToProve) public setUpFor("empty_block_1") { uint256 toProve = bound(_blocksToProve, 0, 2); _testBlock("empty_block_1", toProve > 0); _testBlock("empty_block_2", toProve > 1); @@ -95,7 +109,7 @@ contract RollupTest is DecoderBase { assertEq(rollup.provenBlockCount(), 1 + toProve, "Invalid proven block count"); } - function testRevertInvalidBlockNumber() public { + function testRevertInvalidBlockNumber() public setUpFor("empty_block_1") { DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; @@ -112,7 +126,7 @@ contract RollupTest is DecoderBase { rollup.process(header, archive); } - function testRevertInvalidChainId() public { + function testRevertInvalidChainId() public setUpFor("empty_block_1") { DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; @@ -129,7 +143,7 @@ contract RollupTest is DecoderBase { rollup.process(header, archive); } - function testRevertInvalidVersion() public { + function testRevertInvalidVersion() public setUpFor("empty_block_1") { DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; @@ -145,40 +159,28 @@ contract RollupTest is DecoderBase { rollup.process(header, archive); } - function testRevertTimestampInFuture() public { + function testRevertInvalidTimestamp() public setUpFor("empty_block_1") { DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; bytes memory body = data.body; - uint256 ts = block.timestamp + 1; - assembly { - mstore(add(header, add(0x20, 0x01b4)), ts) - } + uint256 realTs = data.decodedHeader.globalVariables.timestamp; + uint256 badTs = realTs + 1; - availabilityOracle.publish(body); - - vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__TimestampInFuture.selector)); - rollup.process(header, archive); - } - - function testRevertTimestampTooOld() public { - DecoderBase.Data memory data = load("empty_block_1").block; - bytes memory header = data.header; - bytes32 archive = data.archive; - bytes memory body = data.body; + vm.warp(max(block.timestamp, realTs)); - // Beware of the store slot below, if the test is failing might be because of the slot - // We overwrite `lastBlockTs` in the rollup - vm.store(address(rollup), bytes32(uint256(6)), bytes32(uint256(block.timestamp))); + assembly { + mstore(add(header, add(0x20, 0x01b4)), badTs) + } availabilityOracle.publish(body); - vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__TimestampTooOld.selector)); + vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidTimestamp.selector, realTs, badTs)); rollup.process(header, archive); } - function testSubmitProofNonExistantBlock() public { + function testSubmitProofNonExistantBlock() public setUpFor("empty_block_1") { DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; @@ -187,7 +189,7 @@ contract RollupTest is DecoderBase { rollup.submitProof(header, archive, bytes32(0), "", ""); } - function testSubmitProofInvalidArchive() public { + function testSubmitProofInvalidArchive() public setUpFor("empty_block_1") { _testBlock("empty_block_1", false); _testBlock("empty_block_2", false); @@ -208,14 +210,12 @@ contract RollupTest is DecoderBase { rollup.submitProof(header, archive, bytes32(0), "", ""); } - function testSubmitProofInvalidProposedArchive() public { + function testSubmitProofInvalidProposedArchive() public setUpFor("empty_block_1") { + _testBlock("empty_block_1", false); + DecoderBase.Data memory data = load("empty_block_1").block; bytes memory header = data.header; bytes32 archive = data.archive; - bytes memory body = data.body; - - availabilityOracle.publish(body); - rollup.process(header, archive); bytes32 badArchive = keccak256(abi.encode(archive)); diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 5012b68dade..551348f198b 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": "0x10107c16f4b8ac81aa0127268a7c467fd07717e1a6ae8ad0d068c9454b0e976d", + "archive": "0x2b3f280c88146ea26fccb87df4254c4de54914b7785de5a06e36d2b1f380d43f", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { @@ -20,12 +20,12 @@ }, "globalVariables": { "blockNumber": 1, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000001", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000005", "chainId": 31337, - "timestamp": 0, + "timestamp": 1722494487, "version": 1, - "coinbase": "0x7fea02760c190713b363c9030a22b14846464e1f", - "feeRecipient": "0x085fdb7b311018f9d15e25348b849902dd8041515bc78248220ca712a6c6afef", + "coinbase": "0x4879b4a751a0905785f32dc06555e53287f0997a", + "feeRecipient": "0x2c28c48baa0a109600f717e55608b27470c9aa6ef3665a5296417845efe272f9", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -56,8 +56,8 @@ } } }, - "header": "0x0a50781a9ce38c219f4fb0c320c441b30c9d3009dfb36d995a8035e68e67e27d00000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000007fea02760c190713b363c9030a22b14846464e1f085fdb7b311018f9d15e25348b849902dd8041515bc78248220ca712a6c6afef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00d30a4f529fd4f14f9667bc062d5fbf3c7b0dd3e9833a7253732f83aa60986e", + "header": "0x0a50781a9ce38c219f4fb0c320c441b30c9d3009dfb36d995a8035e68e67e27d00000001000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000100021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000066ab2e174879b4a751a0905785f32dc06555e53287f0997a2c28c48baa0a109600f717e55608b27470c9aa6ef3665a5296417845efe272f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0003fffe09cc26276d4ab11598ed1a4de5d5e3155c529ec6f733d3ce360bc3c3", "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 89a277c01a5..7768d6b889b 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": "0x2602de27d40577b24692fc0696b1225a4725e6b7a8a105c658b261d55ee83660", + "archive": "0x0bbd4a944df39dcadb97f52443dd21e5e06ddaf5d53558cc18de0c608b8128f9", "body": "0x00000000", "txsEffectsHash": "0x00d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf2", "decodedHeader": { @@ -20,12 +20,12 @@ }, "globalVariables": { "blockNumber": 2, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000002", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000006", "chainId": 31337, - "timestamp": 1722338614, + "timestamp": 1722494499, "version": 1, - "coinbase": "0x7fea02760c190713b363c9030a22b14846464e1f", - "feeRecipient": "0x085fdb7b311018f9d15e25348b849902dd8041515bc78248220ca712a6c6afef", + "coinbase": "0x4879b4a751a0905785f32dc06555e53287f0997a", + "feeRecipient": "0x2c28c48baa0a109600f717e55608b27470c9aa6ef3665a5296417845efe272f9", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x10107c16f4b8ac81aa0127268a7c467fd07717e1a6ae8ad0d068c9454b0e976d" + "root": "0x2b3f280c88146ea26fccb87df4254c4de54914b7785de5a06e36d2b1f380d43f" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x10107c16f4b8ac81aa0127268a7c467fd07717e1a6ae8ad0d068c9454b0e976d00000002000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000066a8cd367fea02760c190713b363c9030a22b14846464e1f085fdb7b311018f9d15e25348b849902dd8041515bc78248220ca712a6c6afef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x009d843e9fb93a6cf18eb3784737e8fdf2ee10b75aa4843433d10001864f32f6", + "header": "0x2b3f280c88146ea26fccb87df4254c4de54914b7785de5a06e36d2b1f380d43f00000002000000000000000000000000000000000000000000000000000000000000000200d09e7feff5a1049661763ded52742f02aac5d9793b27a40d6b9c60a668bdf200089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f27800000180021a6cc64c830b4914600d0296c3968c5d28c1b00c5c4b0b33d1f39d948edbd4000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000066ab2e234879b4a751a0905785f32dc06555e53287f0997a2c28c48baa0a109600f717e55608b27470c9aa6ef3665a5296417845efe272f9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00ad75bcc1c4513e01ca41842510e77ac0c431a976c98014df04a9362e248d68", "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 02f9efc1649..7ed1dab8fd3 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": "0x10fdfd609222220516ec6ece1a0b4b276c6180bd49a41ecaaa265b6c1b59c3f6", + "archive": "0x28c8c6201a6bd1339945f0eef029c84f6af501aee4ce542dd58f396ffc8a0eab", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e08000000000000000000000000000000000000000000000000000000000000034000000000000000000000000000000000000000000000000000000000000003410000000000000000000000000000000000000000000000000000000000000342000000000000000000000000000000000000000000000000000000000000034300000000000000000000000000000000000000000000000000000000000003440000000000000000000000000000000000000000000000000000000000000345000000000000000000000000000000000000000000000000000000000000034600000000000000000000000000000000000000000000000000000000000003473f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be08000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000003810000000000000000000000000000000000000000000000000000000000000382000000000000000000000000000000000000000000000000000000000000038300000000000000000000000000000000000000000000000000000000000003840000000000000000000000000000000000000000000000000000000000000385000000000000000000000000000000000000000000000000000000000000038600000000000000000000000000000000000000000000000000000000000003873f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c73f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e08000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004010000000000000000000000000000000000000000000000000000000000000402000000000000000000000000000000000000000000000000000000000000040300000000000000000000000000000000000000000000000000000000000004040000000000000000000000000000000000000000000000000000000000000405000000000000000000000000000000000000000000000000000000000000040600000000000000000000000000000000000000000000000000000000000004073f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a3", "decodedHeader": { @@ -70,12 +70,12 @@ }, "globalVariables": { "blockNumber": 1, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000001", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000015", "chainId": 31337, - "timestamp": 0, + "timestamp": 1722494175, "version": 1, - "coinbase": "0x41842b4363045d846eaa01a8e86ca2564fdc2c90", - "feeRecipient": "0x297f601d3a89c639e302667fae3ce5b908d600f790146bc793ec1f92c83d202f", + "coinbase": "0xf182bc4eb95145879c66320644da6cd63211f63a", + "feeRecipient": "0x2f549844f0baaaee3c5828fcdb785136607e7b06be25dda162cfefe369e98d74", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -106,8 +106,8 @@ } } }, - "header": "0x0a50781a9ce38c219f4fb0c320c441b30c9d3009dfb36d995a8035e68e67e27d000000010000000000000000000000000000000000000000000000000000000000000004006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000041842b4363045d846eaa01a8e86ca2564fdc2c90297f601d3a89c639e302667fae3ce5b908d600f790146bc793ec1f92c83d202f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00c4b041454ee7c4a7dce3632faca14d096ce5ba84784eb8fe87462f6a56f58d", + "header": "0x0a50781a9ce38c219f4fb0c320c441b30c9d3009dfb36d995a8035e68e67e27d000000010000000000000000000000000000000000000000000000000000000000000004006e4c1d10533ea35e67118a58a08e56c1c799d33ae60046b88aeb76bc5974a300089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0071556a0e9f403540d572c98a081d21b325e7c802b8b3baf54f3d56fecb22301864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f80000000100d944282e11bdcfa5e8f2b55fe80db4c586087bfc10e0bbba5724d30b8c15e2e0000010001c16141039343d4d403501e66deecff1b024bd76794820a43dc3424087813a2000001802f72d4fe80aa0b43708532e4fb05cdf574bfd36c8c6bba1ff4ec3c6e0ffc9b3a000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000066ab2cdff182bc4eb95145879c66320644da6cd63211f63a2f549844f0baaaee3c5828fcdb785136607e7b06be25dda162cfefe369e98d74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00cc5ccb9ef302006e31302486eac76d82c434a333475a13fac7ad48ba3e5e2f", "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 eb063d65b7c..04a6f5d1bb9 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": "0x0c6613cefa1a117ae5b7fd29c56b37298013d7b6aa29ec2fba2e7711c66abcde", + "archive": "0x1402ae589c5b1cfabdd7bac464af0c529a14118e40f850d57cce3fb8e46ac14e", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000004410000000000000000000000000000000000000000000000000000000000000442000000000000000000000000000000000000000000000000000000000000044300000000000000000000000000000000000000000000000000000000000004440000000000000000000000000000000000000000000000000000000000000445000000000000000000000000000000000000000000000000000000000000044600000000000000000000000000000000000000000000000000000000000004473f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08000000000000000000000000000000000000000000000000000000000000048000000000000000000000000000000000000000000000000000000000000004810000000000000000000000000000000000000000000000000000000000000482000000000000000000000000000000000000000000000000000000000000048300000000000000000000000000000000000000000000000000000000000004840000000000000000000000000000000000000000000000000000000000000485000000000000000000000000000000000000000000000000000000000000048600000000000000000000000000000000000000000000000000000000000004873f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c100000000000000000000000000000000000000000000000000000000000004c200000000000000000000000000000000000000000000000000000000000004c300000000000000000000000000000000000000000000000000000000000004c400000000000000000000000000000000000000000000000000000000000004c500000000000000000000000000000000000000000000000000000000000004c600000000000000000000000000000000000000000000000000000000000004c73f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e08000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000005010000000000000000000000000000000000000000000000000000000000000502000000000000000000000000000000000000000000000000000000000000050300000000000000000000000000000000000000000000000000000000000005040000000000000000000000000000000000000000000000000000000000000505000000000000000000000000000000000000000000000000000000000000050600000000000000000000000000000000000000000000000000000000000005073f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b", "decodedHeader": { @@ -70,12 +70,12 @@ }, "globalVariables": { "blockNumber": 2, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000002", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000026", "chainId": 31337, - "timestamp": 1722338557, + "timestamp": 1722494379, "version": 1, - "coinbase": "0x41842b4363045d846eaa01a8e86ca2564fdc2c90", - "feeRecipient": "0x297f601d3a89c639e302667fae3ce5b908d600f790146bc793ec1f92c83d202f", + "coinbase": "0xf182bc4eb95145879c66320644da6cd63211f63a", + "feeRecipient": "0x2f549844f0baaaee3c5828fcdb785136607e7b06be25dda162cfefe369e98d74", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -83,7 +83,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x10fdfd609222220516ec6ece1a0b4b276c6180bd49a41ecaaa265b6c1b59c3f6" + "root": "0x28c8c6201a6bd1339945f0eef029c84f6af501aee4ce542dd58f396ffc8a0eab" }, "stateReference": { "l1ToL2MessageTree": { @@ -106,8 +106,8 @@ } } }, - "header": "0x10fdfd609222220516ec6ece1a0b4b276c6180bd49a41ecaaa265b6c1b59c3f600000002000000000000000000000000000000000000000000000000000000000000000400c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000066a8ccfd41842b4363045d846eaa01a8e86ca2564fdc2c90297f601d3a89c639e302667fae3ce5b908d600f790146bc793ec1f92c83d202f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00aaf0d78b9742dfc0755ffcc84addac36eabab9bc161267d2381b1a84959f78", + "header": "0x28c8c6201a6bd1339945f0eef029c84f6af501aee4ce542dd58f396ffc8a0eab00000002000000000000000000000000000000000000000000000000000000000000000400c6c40beb1ea89a3546d3527c7f1e86eb3866a40ce5f9854afaefd49f51cd5b00212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb891937008bb57ba402f4917a5169c695e37af3fa10ae64220de709573dbf127d9955e82e0232573b292e99cb24c082c3ef340d619341ab76aa1e9dff1ab1914963452d0000002024c6dc6d357aad01e10fe1adb877bb28b1df97375b874116e488086ca76e5f9600000200268020a622156e2beac47431b0cd70e1c81fef9a6aa3c365bfcbed9aa7301c5e000002802f1b0fefdce35aa5d17156a75b5df1128daa19c74dd56455e4545054d6a48eff000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000066ab2dabf182bc4eb95145879c66320644da6cd63211f63a2f549844f0baaaee3c5828fcdb785136607e7b06be25dda162cfefe369e98d74000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00603bc51673524c9d8c3b24fdaad78bcf9d0bd6c950d7db9a3ff1a52f647387", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index 3cea4e115d1..8f74622bb86 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -15,6 +15,7 @@ import {Inbox} from "../../src/core/messagebridge/Inbox.sol"; import {Outbox} from "../../src/core/messagebridge/Outbox.sol"; import {Errors} from "../../src/core/libraries/Errors.sol"; import {Rollup} from "../../src/core/Rollup.sol"; +import {Leonidas} from "../../src/core/sequencer_selection/Leonidas.sol"; import {AvailabilityOracle} from "../../src/core/availability_oracle/AvailabilityOracle.sol"; import {NaiveMerkle} from "../merkle/Naive.sol"; import {MerkleTestUtil} from "../merkle/TestUtil.sol"; @@ -40,7 +41,20 @@ contract SpartaTest is DecoderBase { SignatureLib.Signature internal emptySignature; - function setUp() public virtual { + /** + * @notice Set up the contracts needed for the tests with time aligned to the provided block name + */ + modifier setup(uint256 _sigCount) { + string memory _name = "mixed_block_1"; + { + Leonidas leo = new Leonidas(address(1)); + DecoderBase.Full memory full = load(_name); + uint256 slotNumber = full.block.decodedHeader.globalVariables.slotNumber; + uint256 initialTime = + full.block.decodedHeader.globalVariables.timestamp - slotNumber * leo.SLOT_DURATION(); + vm.warp(initialTime); + } + registry = new Registry(); availabilityOracle = new AvailabilityOracle(); portalERC20 = new PortalERC20(); @@ -56,15 +70,16 @@ contract SpartaTest is DecoderBase { merkleTestUtil = new MerkleTestUtil(); txsHelper = new TxsDecoderHelper(); - for (uint256 i = 1; i < 5; i++) { + for (uint256 i = 1; i < _sigCount; i++) { uint256 privateKey = uint256(keccak256(abi.encode("validator", i))); address validator = vm.addr(privateKey); privateKeys[validator] = privateKey; rollup.addValidator(validator); } + _; } - function testProposerForNonSetupEpoch(uint8 _epochsToJump) public { + function testProposerForNonSetupEpoch(uint8 _epochsToJump) public setup(5) { uint256 pre = rollup.getCurrentEpoch(); vm.warp( block.timestamp + uint256(_epochsToJump) * rollup.EPOCH_DURATION() * rollup.SLOT_DURATION() @@ -81,21 +96,14 @@ contract SpartaTest is DecoderBase { assertEq(expectedProposer, actualProposer, "Invalid proposer"); } - function testValidatorSetLargerThanCommittee(bool _insufficientSigs) public { + function testValidatorSetLargerThanCommittee(bool _insufficientSigs) public setup(100) { + assertGt(rollup.getValidators().length, rollup.TARGET_COMMITTEE_SIZE(), "Not enough validators"); _testBlock("mixed_block_1", false, 0, false); // We run a block before the epoch with validators - // Adding more validators! - for (uint256 i = 5; i < 100; i++) { - uint256 privateKey = uint256(keccak256(abi.encode("validator", i))); - address validator = vm.addr(privateKey); - privateKeys[validator] = privateKey; - rollup.addValidator(validator); - } - - assertGt(rollup.getValidators().length, rollup.TARGET_COMMITTEE_SIZE(), "Not enough validators"); + uint256 ts = block.timestamp + rollup.EPOCH_DURATION() * rollup.SLOT_DURATION(); uint256 committeSize = rollup.TARGET_COMMITTEE_SIZE() * 2 / 3 + (_insufficientSigs ? 0 : 1); - _testBlock("mixed_block_2", _insufficientSigs, committeSize, false); // We need signatures! + _testBlock("mixed_block_2", _insufficientSigs, committeSize, false, ts); // We need signatures! assertEq( rollup.getEpochCommittee(rollup.getCurrentEpoch()).length, @@ -104,17 +112,17 @@ contract SpartaTest is DecoderBase { ); } - function testHappyPath() public { + function testHappyPath() public setup(5) { _testBlock("mixed_block_1", false, 0, false); // We run a block before the epoch with validators _testBlock("mixed_block_2", false, 3, false); // We need signatures! } - function testInvalidProposer() public { + function testInvalidProposer() public setup(5) { _testBlock("mixed_block_1", false, 0, false); // We run a block before the epoch with validators _testBlock("mixed_block_2", true, 3, true); // We need signatures! } - function testInsufficientSigs() public { + function testInsufficientSigs() public setup(5) { _testBlock("mixed_block_1", false, 0, false); // We run a block before the epoch with validators _testBlock("mixed_block_2", true, 2, false); // We need signatures! } @@ -130,7 +138,17 @@ contract SpartaTest is DecoderBase { bool _expectRevert, uint256 _signatureCount, bool _invalidaProposer - ) public { + ) internal { + _testBlock(_name, _expectRevert, _signatureCount, _invalidaProposer, 0); + } + + function _testBlock( + string memory _name, + bool _expectRevert, + uint256 _signatureCount, + bool _invalidaProposer, + uint256 _ts + ) internal { DecoderBase.Full memory full = load(_name); bytes memory header = full.block.header; bytes32 archive = full.block.archive; @@ -139,7 +157,18 @@ contract SpartaTest is DecoderBase { StructToAvoidDeepStacks memory ree; // We jump to the time of the block. (unless it is in the past) - vm.warp(max(block.timestamp, full.block.decodedHeader.globalVariables.timestamp)); + vm.warp(max(block.timestamp, max(full.block.decodedHeader.globalVariables.timestamp, _ts))); + + if (_ts > 0) { + // Update the timestamp and slot in the header + uint256 slotValue = rollup.getCurrentSlot(); + uint256 timestampMemoryPosition = 0x01b4; + uint256 slotMemoryPosition = 0x0194; + assembly { + mstore(add(header, add(0x20, timestampMemoryPosition)), _ts) + mstore(add(header, add(0x20, slotMemoryPosition)), slotValue) + } + } _populateInbox(full.populate.sender, full.populate.recipient, full.populate.l1ToL2Content); @@ -161,13 +190,19 @@ contract SpartaTest is DecoderBase { signatures[i] = createSignature(validators[i], archive); } - if (_expectRevert && _signatureCount < ree.needed) { - vm.expectRevert( - abi.encodeWithSelector( - Errors.Leonidas__InsufficientAttestations.selector, ree.needed, _signatureCount - ) - ); + if (_expectRevert) { ree.shouldRevert = true; + if (_signatureCount < ree.needed) { + vm.expectRevert( + abi.encodeWithSelector( + Errors.Leonidas__InsufficientAttestationsProvided.selector, + ree.needed, + _signatureCount + ) + ); + } + // @todo Handle SignatureLib__InvalidSignature case + // @todo Handle Leonidas__InsufficientAttestations case } if (_expectRevert && _invalidaProposer) { 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 b48992dec4e..79dcb29da4d 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -128,6 +128,7 @@ global MAX_ARGS_LENGTH: u32 = ARGS_HASH_CHUNK_COUNT * ARGS_HASH_CHUNK_LENGTH; global INITIALIZATION_SLOT_SEPARATOR: Field = 1000_000_000; global INITIAL_L2_BLOCK_NUM: Field = 1; global BLOB_SIZE_IN_BYTES: Field = 31 * 4096; +global ETHEREUM_SLOT_DURATION: u32 = 12; // CONTRACT CLASS CONSTANTS global MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u32 = 20000; diff --git a/yarn-project/archiver/src/archiver/eth_log_handlers.ts b/yarn-project/archiver/src/archiver/eth_log_handlers.ts index 00d0b6d4bef..bd3e8d95d5c 100644 --- a/yarn-project/archiver/src/archiver/eth_log_handlers.ts +++ b/yarn-project/archiver/src/archiver/eth_log_handlers.ts @@ -5,7 +5,16 @@ import { Fr } from '@aztec/foundation/fields'; import { numToUInt32BE } from '@aztec/foundation/serialize'; import { AvailabilityOracleAbi, InboxAbi, RollupAbi } from '@aztec/l1-artifacts'; -import { type Hex, type Log, type PublicClient, decodeFunctionData, getAbiItem, getAddress, hexToBytes } from 'viem'; +import { + type Hex, + type Log, + type PublicClient, + decodeFunctionData, + getAbiItem, + getAddress, + hexToBytes, + slice, +} from 'viem'; /** * Processes newly received MessageSent (L1 to L2) logs. @@ -88,7 +97,7 @@ async function getBlockMetadataFromRollupTx( data, }); - if (functionName !== 'process') { + if (!(functionName === 'process' || functionName === 'publishAndProcess')) { throw new Error(`Unexpected method called ${functionName}`); } const [headerHex, archiveRootHex] = args! as readonly [Hex, Hex]; @@ -113,7 +122,7 @@ async function getBlockMetadataFromRollupTx( /** * Gets block bodies from calldata of an L1 transaction, and deserializes them into Body objects. - * Assumes that the block was published from an EOA. + * @note Assumes that the block was published using `publishAndProcess` or `publish`. * TODO: Add retries and error management. * @param publicClient - The viem public client to use for transaction retrieval. * @param txHash - Hash of the tx that published it. @@ -124,20 +133,38 @@ async function getBlockBodiesFromAvailabilityOracleTx( txHash: `0x${string}`, ): Promise { const { input: data } = await publicClient.getTransaction({ hash: txHash }); - const { functionName, args } = decodeFunctionData({ - abi: AvailabilityOracleAbi, - data, - }); - - if (functionName !== 'publish') { - throw new Error(`Unexpected method called ${functionName}`); + const DATA_INDEX = [3, 2, 0]; + // [ + // "publishAndProcess(bytes calldata _header,bytes32 _archive,SignatureLib.Signature[] memory _signatures,bytes calldata _body)", + // "publishAndProcess(bytes calldata _header,bytes32 _archive,bytes calldata _body)", + // "publish(bytes calldata _body)" + // ] + const SUPPORTED_SIGS = ['0x29a09106', '0xe86e3595', '0x7fd28346']; + + const signature = slice(data, 0, 4); + + if (!SUPPORTED_SIGS.includes(signature)) { + throw new Error(`Unexpected method called ${signature}`); } - const [bodyHex] = args! as [Hex]; - - const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex))); - - return blockBody; + if (signature === SUPPORTED_SIGS[2]) { + const { args } = decodeFunctionData({ + abi: AvailabilityOracleAbi, + data, + }); + const [bodyHex] = args! as [Hex]; + const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex))); + return blockBody; + } else { + const { args } = decodeFunctionData({ + abi: RollupAbi, + data, + }); + const index = SUPPORTED_SIGS.indexOf(signature); + const bodyHex = args![DATA_INDEX[index]] as Hex; + const blockBody = Body.fromBuffer(Buffer.from(hexToBytes(bodyHex))); + return blockBody; + } } /** diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index d05045a8dd2..83266fd6275 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -94,6 +94,18 @@ export class EthCheatCodes { this.logger.info(`Mined ${numberOfBlocks} blocks`); } + /** + * Set the interval between blocks (block time) + * @param interval - The interval to use between blocks + */ + public async setBlockInterval(interval: number): Promise { + const res = await this.rpcCall('anvil_setBlockTimestampInterval', [interval]); + if (res.error) { + throw new Error(`Error setting block interval: ${res.error.message}`); + } + this.logger.info(`Set block interval to ${interval}`); + } + /** * Set the next block timestamp * @param timestamp - The timestamp to set the next block to @@ -106,6 +118,19 @@ export class EthCheatCodes { this.logger.info(`Set next block timestamp to ${timestamp}`); } + /** + * Set the next block timestamp and mines the block + * @param timestamp - The timestamp to set the next block to + */ + public async warp(timestamp: number): Promise { + const res = await this.rpcCall('evm_setNextBlockTimestamp', [timestamp]); + if (res.error) { + throw new Error(`Error warping: ${res.error.message}`); + } + await this.mine(); + this.logger.info(`Warped to ${timestamp}`); + } + /** * Dumps the current chain state to a file. * @param fileName - The file name to dump state into @@ -257,18 +282,12 @@ export class AztecCheatCodes { } /** - * Set time of the next execution on aztec. - * It also modifies time on eth for next execution and stores this time as the last rollup block on the rollup contract. - * @param to - The timestamp to set the next block to (must be greater than current time) + * Get the current timestamp + * @returns The current timestamp */ - public async warp(to: number): Promise { - const rollupContract = (await this.pxe.getNodeInfo()).l1ContractAddresses.rollupAddress; - await this.eth.setNextBlockTimestamp(to); - // also store this time on the rollup contract (slot 2 tracks `lastBlockTs`). - // This is because when the sequencer executes public functions, it uses the timestamp stored in the rollup contract. - await this.eth.store(rollupContract, 6n, BigInt(to)); - // also store this on slot of the rollup contract (`lastWarpedBlockTs`) which tracks the last time warp was used. - await this.eth.store(rollupContract, 7n, BigInt(to)); + public async timestamp(): Promise { + const res = await this.pxe.getBlock(await this.blockNumber()); + return res?.header.globalVariables.timestamp.toNumber() ?? 0; } /** diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 03852b5c8d1..e934afa5c38 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -77,6 +77,7 @@ export const ROOT_PARITY_INDEX = 19; export const BASE_ROLLUP_INDEX = 20; export const MERGE_ROLLUP_INDEX = 21; export const ROOT_ROLLUP_INDEX = 22; +export const ETHEREUM_SLOT_DURATION = 12; export const FUNCTION_SELECTOR_NUM_BYTES = 4; export const ARGS_HASH_CHUNK_LENGTH = 16; export const ARGS_HASH_CHUNK_COUNT = 16; 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 ad29bcce54a..48cd5444e6f 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 @@ -1,6 +1,15 @@ import { type ArchiveSource } from '@aztec/archiver'; import { getConfigEnvVars } from '@aztec/aztec-node'; -import { AztecAddress, Body, Fr, GlobalVariables, type L2Block, createDebugLogger, mockTx } from '@aztec/aztec.js'; +import { + AztecAddress, + Body, + EthCheatCodes, + Fr, + GlobalVariables, + type L2Block, + createDebugLogger, + mockTx, +} from '@aztec/aztec.js'; // eslint-disable-next-line no-restricted-imports import { PROVING_STATUS, @@ -9,6 +18,7 @@ import { makeProcessedTx, } from '@aztec/circuit-types'; import { + ETHEREUM_SLOT_DURATION, EthAddress, GasFees, type Header, @@ -93,11 +103,26 @@ describe('L1Publisher integration', () => { let coinbase: EthAddress; let feeRecipient: AztecAddress; + let ethCheatCodes: EthCheatCodes; + // To update the test data, run "export AZTEC_GENERATE_TEST_DATA=1" in shell and run the tests again // If you have issues with RPC_URL, it is likely that you need to set the RPC_URL in the shell as well // If running ANVIL locally, you can use ETHEREUM_HOST="http://0.0.0.0:8545" const AZTEC_GENERATE_TEST_DATA = !!process.env.AZTEC_GENERATE_TEST_DATA; + const setTimeToNextSlot = async () => { + const currentTime = (await publicClient.getBlock()).timestamp; + const currentSlot = await rollup.read.getCurrentSlot(); + const timestamp = (await rollup.read.getTimestampForSlot([currentSlot + 1n])) - BigInt(ETHEREUM_SLOT_DURATION); + + // @todo @LHerskind figure out why we have issues here if we do not entirely ENTER the next slot + // My guess would be that it is somewhere because of a bad calculation with global variables or such + + if (timestamp > currentTime) { + await ethCheatCodes.warp(Number(timestamp)); + } + }; + beforeEach(async () => { deployerAccount = privateKeyToAccount(deployerPK); ({ l1ContractAddresses, publicClient, walletClient } = await setupL1Contracts( @@ -106,6 +131,8 @@ describe('L1Publisher integration', () => { logger, )); + ethCheatCodes = new EthCheatCodes(config.rpcUrl); + rollupAddress = getAddress(l1ContractAddresses.rollupAddress.toString()); inboxAddress = getAddress(l1ContractAddresses.inboxAddress.toString()); outboxAddress = getAddress(l1ContractAddresses.outboxAddress.toString()); @@ -153,6 +180,8 @@ describe('L1Publisher integration', () => { feeRecipient = config.feeRecipient || AztecAddress.random(); prevHeader = builderDb.getInitialHeader(); + + await setTimeToNextSlot(); }); const makeEmptyProcessedTx = () => @@ -344,12 +373,14 @@ describe('L1Publisher integration', () => { makeBloatedProcessedTx(totalNullifiersPerBlock * i + 4 * MAX_NULLIFIERS_PER_TX), ]; + const ts = (await publicClient.getBlock()).timestamp; + const slot = await rollup.read.getSlotAt([ts + BigInt(ETHEREUM_SLOT_DURATION)]); const globalVariables = new GlobalVariables( new Fr(chainId), new Fr(config.version), new Fr(1 + i), - new Fr(1 + i) /** slot number */, - new Fr(await rollup.read.lastBlockTs()), + new Fr(slot), + new Fr(await rollup.read.getTimestampForSlot([slot])), coinbase, feeRecipient, GasFees.empty(), @@ -391,8 +422,12 @@ describe('L1Publisher integration', () => { const expectedData = encodeFunctionData({ abi: RollupAbi, - functionName: 'process', - args: [`0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`], + functionName: 'publishAndProcess', + args: [ + `0x${block.header.toBuffer().toString('hex')}`, + `0x${block.archive.root.toBuffer().toString('hex')}`, + `0x${block.body.toBuffer().toString('hex')}`, + ], }); expect(ethTx.input).toEqual(expectedData); @@ -423,6 +458,9 @@ describe('L1Publisher integration', () => { currentL1ToL2Messages = nextL1ToL2Messages; // We wipe the messages from previous iteration nextL1ToL2Messages = []; + + // @todo @LHerskind need to make sure that time have progressed to the next slot! + await setTimeToNextSlot(); } }); @@ -436,12 +474,14 @@ describe('L1Publisher integration', () => { const l1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)); const txs = [makeEmptyProcessedTx(), makeEmptyProcessedTx()]; + const ts = (await publicClient.getBlock()).timestamp; + const slot = await rollup.read.getSlotAt([ts + BigInt(ETHEREUM_SLOT_DURATION)]); const globalVariables = new GlobalVariables( new Fr(chainId), new Fr(config.version), new Fr(1 + i), - new Fr(1 + i) /** slot number */, - new Fr(await rollup.read.lastBlockTs()), + new Fr(slot), + new Fr(await rollup.read.getTimestampForSlot([slot])), coinbase, feeRecipient, GasFees.empty(), @@ -475,12 +515,28 @@ describe('L1Publisher integration', () => { hash: logs[i].transactionHash!, }); - const expectedData = encodeFunctionData({ - abi: RollupAbi, - functionName: 'process', - args: [`0x${block.header.toBuffer().toString('hex')}`, `0x${block.archive.root.toBuffer().toString('hex')}`], - }); + const expectedData = + i == 0 + ? encodeFunctionData({ + abi: RollupAbi, + functionName: 'publishAndProcess', + args: [ + `0x${block.header.toBuffer().toString('hex')}`, + `0x${block.archive.root.toBuffer().toString('hex')}`, + `0x${block.body.toBuffer().toString('hex')}`, + ], + }) + : encodeFunctionData({ + abi: RollupAbi, + functionName: 'process', + args: [ + `0x${block.header.toBuffer().toString('hex')}`, + `0x${block.archive.root.toBuffer().toString('hex')}`, + ], + }); expect(ethTx.input).toEqual(expectedData); + + await setTimeToNextSlot(); } }); }); diff --git a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts index 562a7fef0da..27d7124d6c5 100644 --- a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts +++ b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts @@ -9,19 +9,9 @@ import { type Wallet, computeSecretHash, } from '@aztec/aztec.js'; -import { RollupAbi } from '@aztec/l1-artifacts'; -import { TestContract, TokenContract } from '@aztec/noir-contracts.js'; +import { TokenContract } from '@aztec/noir-contracts.js'; -import { - type Account, - type Chain, - type HttpTransport, - type PublicClient, - type WalletClient, - getAddress, - getContract, - parseEther, -} from 'viem'; +import { type Account, type Chain, type HttpTransport, type PublicClient, type WalletClient, parseEther } from 'viem'; import { setup } from './fixtures/utils.js'; @@ -34,7 +24,6 @@ describe('e2e_cheat_codes', () => { let walletClient: WalletClient; let publicClient: PublicClient; - let rollupAddress: EthAddress; let token: TokenContract; beforeAll(async () => { @@ -43,7 +32,6 @@ describe('e2e_cheat_codes', () => { walletClient = deployL1ContractsValues.walletClient; publicClient = deployL1ContractsValues.publicClient; - rollupAddress = deployL1ContractsValues.l1ContractAddresses.rollupAddress; admin = wallet.getCompleteAddress(); token = await TokenContract.deploy(wallet, admin, 'TokenName', 'TokenSymbol', 18).send().deployed(); @@ -158,45 +146,6 @@ describe('e2e_cheat_codes', () => { }); describe('L2 cheatcodes', () => { - describe('warp L2 Block Time', () => { - it('can modify L2 block time', async () => { - const contract = await TestContract.deploy(wallet).send().deployed(); - - // now update time: - const timestamp = await cc.eth.timestamp(); - const newTimestamp = timestamp + 100_000_000; - await cc.aztec.warp(newTimestamp); - - // ensure rollup contract is correctly updated - const rollup = getContract({ - address: getAddress(rollupAddress.toString()), - abi: RollupAbi, - client: publicClient, - }); - expect(Number(await rollup.read.lastBlockTs())).toEqual(newTimestamp); - expect(Number(await rollup.read.lastWarpedBlockTs())).toEqual(newTimestamp); - - await contract.methods.is_time_equal(newTimestamp).send().wait({ interval: 0.1 }); - - // Since last rollup block was warped, txs for this rollup will have time incremented by 1 - // See https://github.com/AztecProtocol/aztec-packages/issues/1614 for details - await contract.methods - .is_time_equal(newTimestamp + 1) - .send() - .wait({ interval: 0.1 }); - // block is published at t >= newTimestamp + 1. - expect(Number(await rollup.read.lastBlockTs())).toBeGreaterThanOrEqual(newTimestamp + 1); - }); - - it('should throw if setting L2 block time to a past timestamp', async () => { - const timestamp = await cc.eth.timestamp(); - const pastTimestamp = timestamp - 1000; - await expect(async () => await cc.aztec.warp(pastTimestamp)).rejects.toThrow( - `Error setting next block timestamp: Timestamp error: ${pastTimestamp} is lower than or equal to previous block's timestamp`, - ); - }); - }); - it('load public', async () => { expect(await cc.aztec.loadPublic(token.address, 1n)).toEqual(admin.address.toField()); }); diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index 0de4fac6276..f8bca5cabfa 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -417,7 +417,7 @@ describe('e2e_crowdfunding_and_claim', () => { } // 2) We set next block timestamp to be after the deadline - await cheatCodes.aztec.warp(deadline + 1); + await cheatCodes.eth.warp(deadline + 1); // 3) We donate to the crowdfunding contract await expect( diff --git a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts index 9d1c0007931..821d30fdd8c 100644 --- a/yarn-project/end-to-end/src/e2e_lending_contract.test.ts +++ b/yarn-project/end-to-end/src/e2e_lending_contract.test.ts @@ -2,14 +2,17 @@ import { type AccountWallet, type CheatCodes, type DebugLogger, + type DeployL1Contracts, ExtendedNote, Fr, Note, computeSecretHash, } from '@aztec/aztec.js'; +import { RollupAbi } from '@aztec/l1-artifacts'; import { LendingContract, PriceFeedContract, TokenContract } from '@aztec/noir-contracts.js'; import { jest } from '@jest/globals'; +import { getContract } from 'viem'; import { publicDeployAccounts, setup } from './fixtures/utils.js'; import { LendingAccount, LendingSimulator, TokenSimulator } from './simulators/index.js'; @@ -17,12 +20,13 @@ import { LendingAccount, LendingSimulator, TokenSimulator } from './simulators/i describe('e2e_lending_contract', () => { jest.setTimeout(100_000); let wallet: AccountWallet; + let deployL1ContractsValues: DeployL1Contracts; let logger: DebugLogger; let teardown: () => Promise; let cc: CheatCodes; - const TIME_JUMP = 100; + const SLOT_JUMP = 10; let lendingContract: LendingContract; let priceFeedContract: PriceFeedContract; @@ -60,10 +64,16 @@ describe('e2e_lending_contract', () => { }; beforeAll(async () => { - ({ teardown, logger, cheatCodes: cc, wallet } = await setup(1)); + ({ teardown, logger, cheatCodes: cc, wallet, deployL1ContractsValues } = await setup(1)); ({ lendingContract, priceFeedContract, collateralAsset, stableCoin } = await deployContracts()); await publicDeployAccounts(wallet, [wallet]); + const rollup = getContract({ + address: deployL1ContractsValues.l1ContractAddresses.rollupAddress.toString(), + abi: RollupAbi, + client: deployL1ContractsValues.publicClient, + }); + lendingAccount = new LendingAccount(wallet.getAddress(), new Fr(42)); // Also specified in `noir-contracts/contracts/lending_contract/src/main.nr` @@ -72,6 +82,7 @@ describe('e2e_lending_contract', () => { cc, lendingAccount, rate, + rollup, lendingContract, new TokenSimulator(collateralAsset, wallet, logger, [lendingContract.address, wallet.getAddress()]), new TokenSimulator(stableCoin, wallet, logger, [lendingContract.address, wallet.getAddress()]), @@ -143,7 +154,7 @@ describe('e2e_lending_contract', () => { caller: lendingContract.address, action: collateralAsset.methods.unshield(lendingAccount.address, lendingContract.address, depositAmount, nonce), }); - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.depositPrivate(lendingAccount.address, lendingAccount.key(), depositAmount); // Make a private deposit of funds into own account. @@ -173,7 +184,7 @@ describe('e2e_lending_contract', () => { action: collateralAsset.methods.unshield(lendingAccount.address, lendingContract.address, depositAmount, nonce), }); - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.depositPrivate(lendingAccount.address, lendingAccount.address.toField(), depositAmount); // Make a private deposit of funds into another account, in this case, a public account. // This should: @@ -216,7 +227,7 @@ describe('e2e_lending_contract', () => { .send() .wait(); - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.depositPublic(lendingAccount.address, lendingAccount.address.toField(), depositAmount); // Make a public deposit of funds into self. @@ -236,7 +247,7 @@ describe('e2e_lending_contract', () => { describe('Borrow', () => { it('Borrow 🥸 : 🏦 -> 🍌', async () => { const borrowAmount = 69n; - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.borrow(lendingAccount.key(), lendingAccount.address, borrowAmount); // Make a private borrow using the private account @@ -254,7 +265,7 @@ describe('e2e_lending_contract', () => { it('Borrow: 🏦 -> 🍌', async () => { const borrowAmount = 69n; - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.borrow(lendingAccount.address.toField(), lendingAccount.address, borrowAmount); // Make a public borrow using the private account @@ -277,7 +288,7 @@ describe('e2e_lending_contract', () => { action: stableCoin.methods.burn(lendingAccount.address, repayAmount, nonce), }); - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.repayPrivate(lendingAccount.address, lendingAccount.key(), repayAmount); // Make a private repay of the debt in the private account @@ -301,7 +312,7 @@ describe('e2e_lending_contract', () => { action: stableCoin.methods.burn(lendingAccount.address, repayAmount, nonce), }); - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.repayPrivate(lendingAccount.address, lendingAccount.address.toField(), repayAmount); // Make a private repay of the debt in the public account @@ -333,7 +344,7 @@ describe('e2e_lending_contract', () => { .send() .wait(); - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.repayPublic(lendingAccount.address, lendingAccount.address.toField(), repayAmount); // Make a public repay of the debt in the public account @@ -353,7 +364,7 @@ describe('e2e_lending_contract', () => { describe('Withdraw', () => { it('Withdraw: 🏦 -> 💰', async () => { const withdrawAmount = 42n; - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.withdraw(lendingAccount.address.toField(), lendingAccount.address, withdrawAmount); // Withdraw funds from the public account @@ -368,7 +379,7 @@ describe('e2e_lending_contract', () => { it('Withdraw 🥸 : 🏦 -> 💰', async () => { const withdrawAmount = 42n; - await lendingSim.progressTime(TIME_JUMP); + await lendingSim.progressSlots(SLOT_JUMP); lendingSim.withdraw(lendingAccount.key(), lendingAccount.address, withdrawAmount); // Withdraw funds from the private account diff --git a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts index 81f12ef8a8c..7b60675d080 100644 --- a/yarn-project/end-to-end/src/guides/dapp_testing.test.ts +++ b/yarn-project/end-to-end/src/guides/dapp_testing.test.ts @@ -111,29 +111,6 @@ describe('guides/dapp/testing', () => { }); }); - describe('cheats', () => { - let pxe: PXE; - let owner: AccountWallet; - let testContract: TestContract; - let cheats: CheatCodes; - - beforeAll(async () => { - pxe = createPXEClient(PXE_URL); - owner = await createAccount(pxe); - testContract = await TestContract.deploy(owner).send().deployed(); - cheats = CheatCodes.create(ETHEREUM_HOST, pxe); - }); - - // TODO(@spalladino) Disabled due to flakiness after #7347. Note that warp is already tested in e2e_cheat_codes. - it.skip('warps time to 1h into the future', async () => { - // docs:start:warp - const newTimestamp = Math.floor(Date.now() / 1000) + 60 * 60 * 24; - await cheats.aztec.warp(newTimestamp); - await testContract.methods.is_time_equal(newTimestamp).send().wait(); - // docs:end:warp - }); - }); - describe('assertions', () => { let pxe: PXE; let owner: AccountWallet; diff --git a/yarn-project/end-to-end/src/simulators/lending_simulator.ts b/yarn-project/end-to-end/src/simulators/lending_simulator.ts index 95805f00421..06d258bb51b 100644 --- a/yarn-project/end-to-end/src/simulators/lending_simulator.ts +++ b/yarn-project/end-to-end/src/simulators/lending_simulator.ts @@ -1,8 +1,12 @@ // Convenience struct to hold an account's address and secret that can easily be passed around. import { type AztecAddress, type CheatCodes, Fr } from '@aztec/aztec.js'; +import { ETHEREUM_SLOT_DURATION } from '@aztec/circuits.js'; import { pedersenHash } from '@aztec/foundation/crypto'; +import { type RollupAbi } from '@aztec/l1-artifacts'; import { type LendingContract } from '@aztec/noir-contracts.js/Lending'; +import { type Chain, type GetContractReturnType, type HttpTransport, type PublicClient } from 'viem'; + import { type TokenSimulator } from './token_simulator.js'; /** @@ -76,6 +80,8 @@ export class LendingSimulator { private cc: CheatCodes, private account: LendingAccount, private rate: bigint, + /** the rollup contract */ + public rollup: GetContractReturnType>, /** the lending contract */ public lendingContract: LendingContract, /** the collateral asset used in the lending contract */ @@ -86,15 +92,25 @@ export class LendingSimulator { async prepare() { this.accumulator = BASE; - const ts = await this.cc.eth.timestamp(); - this.time = ts + 10 + (ts % 10); - await this.cc.aztec.warp(this.time); + const slot = await this.rollup.read.getSlotAt([ + BigInt(await this.cc.eth.timestamp()) + BigInt(ETHEREUM_SLOT_DURATION), + ]); + this.time = Number(await this.rollup.read.getTimestampForSlot([slot])); } - async progressTime(diff: number) { - this.time = this.time + diff; - await this.cc.aztec.warp(this.time); - this.accumulator = muldivDown(this.accumulator, computeMultiplier(this.rate, BigInt(diff)), BASE); + async progressSlots(diff: number) { + if (diff <= 1) { + return; + } + + const slot = await this.rollup.read.getSlotAt([BigInt(await this.cc.eth.timestamp())]); + const ts = Number(await this.rollup.read.getTimestampForSlot([slot + BigInt(diff)])); + const timeDiff = ts - this.time; + this.time = ts; + + // Mine ethereum blocks such that the next block will be in a new slot + await this.cc.eth.warp(this.time - ETHEREUM_SLOT_DURATION); + this.accumulator = muldivDown(this.accumulator, computeMultiplier(this.rate, BigInt(timeDiff)), BASE); } depositPrivate(from: AztecAddress, onBehalfOf: Fr, amount: bigint) { diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index 3013cf45795..1ebf9aae763 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -143,6 +143,25 @@ export const deployL1Contracts = async ( contractsToDeploy: L1ContractArtifactsForDeployment, args: { l2GasTokenAddress: AztecAddress; vkTreeRoot: Fr }, ): Promise => { + // We are assuming that you are running this on a local anvil node which have 1s block times + // To align better with actual deployment, we update the block interval to 12s + // The code is same as `setBlockInterval` in `cheat_codes.ts` + const rpcCall = async (rpcUrl: string, method: string, params: any[]) => { + const paramsString = JSON.stringify(params); + const content = { + body: `{"jsonrpc":"2.0", "method": "${method}", "params": ${paramsString}, "id": 1}`, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + }; + return await (await fetch(rpcUrl, content)).json(); + }; + const interval = 12; + const res = await rpcCall(rpcUrl, 'anvil_setBlockTimestampInterval', [interval]); + if (res.error) { + throw new Error(`Error setting block interval: ${res.error.message}`); + } + logger.info(`Set block interval to ${interval}`); + logger.debug('Deploying contracts...'); const walletClient = createWalletClient({ diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index e3ad5b357af..a706714b02f 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -135,7 +135,9 @@ export class ProvingOrchestrator { } // Cancel any currently proving block before starting a new one this.cancelBlock(); - logger.info(`Starting new block with ${numTxs} transactions`); + logger.info( + `Starting block ${globalVariables.blockNumber} for slot ${globalVariables.slotNumber} with ${numTxs} transactions`, + ); // we start the block by enqueueing all of the base parity circuits let baseParityInputs: BaseParityInputs[] = []; let l1ToL2MessagesPadded: Tuple; 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 bf2a676eef1..6ba6e3a1f79 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 @@ -1,4 +1,10 @@ -import { type AztecAddress, type EthAddress, GasFees, GlobalVariables } from '@aztec/circuits.js'; +import { + type AztecAddress, + ETHEREUM_SLOT_DURATION, + type EthAddress, + GasFees, + GlobalVariables, +} from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -6,11 +12,6 @@ import { createDebugLogger } from '@aztec/foundation/log'; * Reads values from L1 state that is used for the global values. */ export interface L1GlobalReader { - /** - * Fetches the last timestamp that a block was processed by the contract. - * @returns The last timestamp that a block was processed by the contract. - */ - getLastTimestamp(): Promise; /** * Fetches the version of the rollup contract. * @returns The version of the rollup contract. @@ -28,17 +29,24 @@ export interface L1GlobalReader { */ getL1CurrentTime(): Promise; - /** - * Gets the last time L2 was warped as tracked by the rollup contract. - * @returns The warped time. - */ - getLastWarpedBlockTs(): Promise; - /** * Gets the current slot. * @returns The current slot. */ getCurrentSlot(): Promise; + + /** + * Get the slot for a specific timestamp. + * @param timestamp - The timestamp to get the slot for. + */ + getSlotAt(timestamp: readonly [bigint]): Promise; + + /** + * Gets the timestamp for a slot + * @param slot - The slot to get the timestamp for. + * @returns The timestamp for the slot. + */ + getTimestampForSlot(slot: readonly [bigint]): Promise; } /** @@ -75,37 +83,30 @@ export class SimpleTestGlobalVariableBuilder implements GlobalVariableBuilder { coinbase: EthAddress, feeRecipient: AztecAddress, ): Promise { - let lastTimestamp = new Fr(await this.reader.getLastTimestamp()); - const version = new Fr(await this.reader.getVersion()); - const chainId = new Fr(await this.reader.getChainId()); + // Not just the current slot, the slot of the next block. + const ts = (await this.reader.getL1CurrentTime()) + BigInt(ETHEREUM_SLOT_DURATION); - // TODO(rahul) - fix #1614. By using the cheatcode warp to modify L2 time, - // txs in the next rollup would have same time as the txs in the current rollup (i.e. the rollup that was warped). - // So, for now you check if L2 time was warped and if so, serve warpedTime + 1 to txs in the new rollup. - // Check if L2 time was warped in the last rollup by checking if current L1 time is same as the warpedTime (stored on the rollup contract). - // more details at https://github.com/AztecProtocol/aztec-packages/issues/1614 + const slot = await this.reader.getSlotAt([ts]); + const timestamp = await this.reader.getTimestampForSlot([slot]); - const currTimestamp = await this.reader.getL1CurrentTime(); - const rollupWarpTime = await this.reader.getLastWarpedBlockTs(); - const isLastBlockWarped = rollupWarpTime === currTimestamp; - if (isLastBlockWarped) { - lastTimestamp = new Fr(lastTimestamp.value + 1n); - } + const slotFr = new Fr(slot); + const timestampFr = new Fr(timestamp); - const slot = new Fr(await this.reader.getCurrentSlot()); + const version = new Fr(await this.reader.getVersion()); + const chainId = new Fr(await this.reader.getChainId()); const gasFees = GasFees.default(); const globalVariables = new GlobalVariables( chainId, version, blockNumber, - slot, - lastTimestamp, + slotFr, + timestampFr, coinbase, feeRecipient, gasFees, ); this.log.debug(`Built global variables for block ${blockNumber}`, globalVariables.toJSON()); - return new GlobalVariables(chainId, version, blockNumber, slot, lastTimestamp, coinbase, feeRecipient, gasFees); + return globalVariables; } } diff --git a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts index 10db14cf42d..29e11846523 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts @@ -39,10 +39,6 @@ export class ViemReader implements L1GlobalReader { }); } - public async getLastTimestamp(): Promise { - return BigInt(await this.rollupContract.read.lastBlockTs()); - } - public async getVersion(): Promise { return BigInt(await this.rollupContract.read.VERSION()); } @@ -55,11 +51,15 @@ export class ViemReader implements L1GlobalReader { return await Promise.resolve((await this.publicClient.getBlock()).timestamp); } - public async getLastWarpedBlockTs(): Promise { - return BigInt(await this.rollupContract.read.lastWarpedBlockTs()); - } - public async getCurrentSlot(): Promise { return BigInt(await this.rollupContract.read.getCurrentSlot()); } + + public async getSlotAt(timestamp: readonly [bigint]): Promise { + return BigInt(await this.rollupContract.read.getSlotAt(timestamp)); + } + + public async getTimestampForSlot(slot: readonly [bigint]): Promise { + return BigInt(await this.rollupContract.read.getTimestampForSlot(slot)); + } } 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 6ceaa3d6f1b..42a2ed15b8b 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -9,8 +9,10 @@ describe('L1Publisher', () => { let txSender: MockProxy; let publishTxHash: string; let processTxHash: string; + let publishAndProcessTxHash: string; let processTxReceipt: MinimalTransactionReceipt; let publishTxReceipt: MinimalTransactionReceipt; + let publishAndProcessTxReceipt: MinimalTransactionReceipt; let l2Block: L2Block; let header: Buffer; @@ -32,6 +34,7 @@ describe('L1Publisher', () => { publishTxHash = `0x${Buffer.from('txHashPublish').toString('hex')}`; // random tx hash processTxHash = `0x${Buffer.from('txHashProcess').toString('hex')}`; // random tx hash + publishAndProcessTxHash = `0x${Buffer.from('txHashPublishAndProcess').toString('hex')}`; // random tx hash publishTxReceipt = { transactionHash: publishTxHash, status: true, @@ -42,8 +45,14 @@ describe('L1Publisher', () => { status: true, logs: [{ data: '' }], } as MinimalTransactionReceipt; + publishAndProcessTxReceipt = { + transactionHash: publishAndProcessTxHash, + status: true, + logs: [{ data: txsEffectsHash.toString('hex') }], + } as MinimalTransactionReceipt; txSender.sendPublishTx.mockResolvedValueOnce(publishTxHash); txSender.sendProcessTx.mockResolvedValueOnce(processTxHash); + txSender.sendPublishAndProcessTx.mockResolvedValueOnce(publishAndProcessTxHash); txSender.getTransactionReceipt.mockResolvedValueOnce(publishTxReceipt).mockResolvedValueOnce(processTxReceipt); txSender.getCurrentArchive.mockResolvedValue(l2Block.header.lastArchive.root.toBuffer()); @@ -53,6 +62,16 @@ describe('L1Publisher', () => { it('publishes l2 block to l1', async () => { const result = await publisher.processL2Block(l2Block); + expect(result).toEqual(true); + expect(txSender.sendPublishAndProcessTx).toHaveBeenCalledWith({ header, archive, body }); + expect(txSender.getTransactionReceipt).toHaveBeenCalledWith(publishAndProcessTxHash); + }); + + it('publishes l2 block to l1 (already published body)', async () => { + txSender.checkIfTxsAreAvailable.mockResolvedValueOnce(true); + + const result = await publisher.processL2Block(l2Block); + expect(result).toEqual(true); expect(txSender.sendProcessTx).toHaveBeenCalledWith({ header, archive, body }); expect(txSender.getTransactionReceipt).toHaveBeenCalledWith(processTxHash); @@ -64,44 +83,56 @@ describe('L1Publisher', () => { expect(result).toBe(false); expect(txSender.sendPublishTx).not.toHaveBeenCalled(); expect(txSender.sendProcessTx).not.toHaveBeenCalled(); + expect(txSender.sendPublishAndProcessTx).not.toHaveBeenCalled(); }); - it('does not retry if sending a publish tx fails', async () => { - txSender.sendPublishTx.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(publishTxHash); + it('does not retry if sending a process tx fails', async () => { + txSender.checkIfTxsAreAvailable.mockResolvedValueOnce(true); + txSender.sendProcessTx.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(processTxHash); const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); - expect(txSender.sendPublishTx).toHaveBeenCalledTimes(1); - expect(txSender.sendProcessTx).toHaveBeenCalledTimes(0); + expect(txSender.sendProcessTx).toHaveBeenCalledTimes(1); }); - it('does not retry if sending a process tx fails', async () => { - txSender.sendProcessTx.mockReset().mockRejectedValueOnce(new Error()).mockResolvedValueOnce(processTxHash); + it('does not retry if sending a publish and process tx fails', async () => { + txSender.sendPublishAndProcessTx.mockReset().mockRejectedValueOnce(new Error()); + // .mockResolvedValueOnce(publishAndProcessTxHash); const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); - expect(txSender.sendPublishTx).toHaveBeenCalledTimes(1); - expect(txSender.sendProcessTx).toHaveBeenCalledTimes(1); + expect(txSender.sendPublishAndProcessTx).toHaveBeenCalledTimes(1); }); - it('retries if fetching the receipt fails', async () => { + it('retries if fetching the receipt fails (process)', async () => { + txSender.checkIfTxsAreAvailable.mockResolvedValueOnce(true); txSender.getTransactionReceipt .mockReset() .mockRejectedValueOnce(new Error()) - .mockResolvedValueOnce(publishTxReceipt) - .mockRejectedValueOnce(new Error()) .mockResolvedValueOnce(processTxReceipt); const result = await publisher.processL2Block(l2Block); expect(result).toEqual(true); - expect(txSender.getTransactionReceipt).toHaveBeenCalledTimes(4); + expect(txSender.getTransactionReceipt).toHaveBeenCalledTimes(2); }); - it('returns false if publish tx reverts', async () => { - txSender.getTransactionReceipt.mockReset().mockResolvedValueOnce({ ...publishTxReceipt, status: false }); + it('retries if fetching the receipt fails (publish process)', async () => { + txSender.getTransactionReceipt + .mockReset() + .mockRejectedValueOnce(new Error()) + .mockResolvedValueOnce(publishAndProcessTxReceipt); + + const result = await publisher.processL2Block(l2Block); + + expect(result).toEqual(true); + expect(txSender.getTransactionReceipt).toHaveBeenCalledTimes(2); + }); + + it('returns false if publish and process tx reverts', async () => { + txSender.getTransactionReceipt.mockReset().mockResolvedValueOnce({ ...publishAndProcessTxReceipt, status: false }); const result = await publisher.processL2Block(l2Block); @@ -109,18 +140,16 @@ describe('L1Publisher', () => { }); it('returns false if process tx reverts', async () => { - txSender.getTransactionReceipt - .mockReset() - .mockResolvedValueOnce(publishTxReceipt) - .mockResolvedValueOnce({ ...publishTxReceipt, status: false }); + txSender.checkIfTxsAreAvailable.mockResolvedValueOnce(true); + txSender.getTransactionReceipt.mockReset().mockResolvedValueOnce({ ...processTxReceipt, status: false }); const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); }); - it('returns false if sending publish tx is interrupted', async () => { - txSender.sendPublishTx.mockReset().mockImplementationOnce(() => sleep(10, publishTxHash)); + it('returns false if sending publish and progress tx is interrupted', async () => { + txSender.sendPublishAndProcessTx.mockReset().mockImplementationOnce(() => sleep(10, publishAndProcessTxHash)); const resultPromise = publisher.processL2Block(l2Block); publisher.interrupt(); @@ -131,6 +160,7 @@ describe('L1Publisher', () => { }); it('returns false if sending process tx is interrupted', async () => { + txSender.checkIfTxsAreAvailable.mockResolvedValueOnce(true); txSender.sendProcessTx.mockReset().mockImplementationOnce(() => sleep(10, processTxHash)); const resultPromise = publisher.processL2Block(l2Block); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 7ea4c48bd46..4004a05760f 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -46,8 +46,8 @@ export interface L1PublisherTxSender { /** Returns the EOA used for sending txs to L1. */ getSenderAddress(): Promise; - /** Returns the address of the current proposer or zero if anyone can submit. */ - getSubmitterAddressForBlock(): Promise; + /** Returns the address of the L2 proposer at the NEXT Ethereum block zero if anyone can submit. */ + getProposerAtNextEthBlock(): Promise; /** * Publishes tx effects to Availability Oracle. @@ -63,6 +63,13 @@ export interface L1PublisherTxSender { */ sendProcessTx(encodedData: L1ProcessArgs): Promise; + /** + * Publishes tx effects to availability oracle and send L2 block to rollup contract + * @param encodedData - Data for processing the new L2 block. + * @returns The hash of the tx. + */ + sendPublishAndProcessTx(encodedData: L1ProcessArgs): Promise; + /** * Sends a tx to the L1 rollup contract with a proof. Returns once the tx has been mined. * @param encodedData - Serialized data for processing the new L2 block. @@ -140,7 +147,7 @@ export class L1Publisher implements L2BlockReceiver { } public async isItMyTurnToSubmit(): Promise { - const submitter = await this.txSender.getSubmitterAddressForBlock(); + const submitter = await this.txSender.getProposerAtNextEthBlock(); const sender = await this.txSender.getSenderAddress(); return submitter.isZero() || submitter.equals(sender); } @@ -158,58 +165,33 @@ export class L1Publisher implements L2BlockReceiver { this.log.info(`Detected different last archive prior to publishing a block, aborting publish...`, ctx); return false; } - const encodedBody = block.body.toBuffer(); - // Publish block transaction effects + // Process block and publish the body if needed (if not already published) while (!this.interrupted) { - if (await this.txSender.checkIfTxsAreAvailable(block)) { - this.log.verbose(`Transaction effects of block ${block.number} already published.`, ctx); - break; - } + const processTxArgs = { + header: block.header.toBuffer(), + archive: block.archive.root.toBuffer(), + body: encodedBody, + }; - const txHash = await this.sendPublishTx(encodedBody); - if (!txHash) { - return false; - } - - const receipt = await this.getTransactionReceipt(txHash); - if (!receipt) { - return false; - } + let txHash; - if (receipt.status) { - let txsEffectsHash; - if (receipt.logs.length === 1) { - // txsEffectsHash from IAvailabilityOracle.TxsPublished event - txsEffectsHash = receipt.logs[0].data; - } else { - this.log.warn(`Expected 1 log, got ${receipt.logs.length}`, ctx); - } - - this.log.info(`Block txs effects published`, { ...ctx, txsEffectsHash }); - break; + if (await this.txSender.checkIfTxsAreAvailable(block)) { + this.log.verbose(`Transaction effects of block ${block.number} already published.`, ctx); + txHash = await this.sendProcessTx(processTxArgs); + } else { + txHash = await this.sendPublishAndProcessTx(processTxArgs); } - this.log.error(`AvailabilityOracle.publish tx status failed: ${receipt.transactionHash}`, ctx); - await this.sleepOrInterrupted(); - } - - const processTxArgs = { - header: block.header.toBuffer(), - archive: block.archive.root.toBuffer(), - body: encodedBody, - }; - - // Process block - while (!this.interrupted) { - const txHash = await this.sendProcessTx(processTxArgs); if (!txHash) { + this.log.info(`Failed to publish block ${block.number} to L1`, ctx); break; } const receipt = await this.getTransactionReceipt(txHash); if (!receipt) { + this.log.info(`Failed to get receipt for tx ${txHash}`, ctx); break; } @@ -354,6 +336,17 @@ export class L1Publisher implements L2BlockReceiver { } } + private async sendPublishAndProcessTx(encodedData: L1ProcessArgs): Promise { + while (!this.interrupted) { + try { + return await this.txSender.sendPublishAndProcessTx(encodedData); + } catch (err) { + this.log.error(`Rollup publish failed`, err); + return undefined; + } + } + } + private async getTransactionReceipt(txHash: string): Promise { while (!this.interrupted) { try { diff --git a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts index 8669c13701f..ca5c3cfe64f 100644 --- a/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts +++ b/yarn-project/sequencer-client/src/publisher/viem-tx-sender.ts @@ -1,5 +1,5 @@ import { type L2Block } from '@aztec/circuit-types'; -import { EthAddress } from '@aztec/circuits.js'; +import { ETHEREUM_SLOT_DURATION, EthAddress } from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; import { createDebugLogger } from '@aztec/foundation/log'; import { AvailabilityOracleAbi, RollupAbi } from '@aztec/l1-artifacts'; @@ -77,9 +77,13 @@ export class ViemTxSender implements L1PublisherTxSender { return Promise.resolve(EthAddress.fromString(this.account.address)); } - async getSubmitterAddressForBlock(): Promise { + // Computes who will be the L2 proposer at the next Ethereum block + // Using next Ethereum block so we do NOT need to wait for it being mined before seeing the effect + // @note Assumes that all ethereum slots have blocks + async getProposerAtNextEthBlock(): Promise { try { - const submitter = await this.rollupContract.read.getCurrentProposer(); + const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); + const submitter = await this.rollupContract.read.getProposerAt([ts]); return EthAddress.fromString(submitter); } catch (err) { this.log.warn(`Failed to get submitter: ${err}`); @@ -170,6 +174,29 @@ export class ViemTxSender implements L1PublisherTxSender { return hash; } + /** + * @notice Publishes the body AND process the block in one transaction + * @param encodedData - Serialized data for processing the new L2 block. + * @param encodedBody - Encoded block body. + * @returns The hash of the transaction + */ + async sendPublishAndProcessTx(encodedData: ProcessTxArgs): Promise { + const args = [ + `0x${encodedData.header.toString('hex')}`, + `0x${encodedData.archive.toString('hex')}`, + `0x${encodedData.body.toString('hex')}`, + ] as const; + + const gas = await this.rollupContract.estimateGas.publishAndProcess(args, { + account: this.account, + }); + const hash = await this.rollupContract.write.publishAndProcess(args, { + gas, + account: this.account, + }); + return hash; + } + /** * Sends a tx to the L1 rollup contract with a proof. Returns once the tx has been mined. * @param encodedData - Serialized data for the proof. diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index f21cb1eec8e..c2f40d05c7a 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -135,36 +135,29 @@ describe('sequencer', () => { proverClient.startNewBlock.mockResolvedValueOnce(ticket); proverClient.finaliseBlock.mockResolvedValue({ block, aggregationObject: [], proof }); publisher.processL2Block.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables( - chainId, - version, - block.header.globalVariables.blockNumber, - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + + const mockedGlobalVariables = new GlobalVariables( + chainId, + version, + new Fr(lastBlockNumber + 1), + block.header.globalVariables.slotNumber, + Fr.ZERO, + coinbase, + feeRecipient, + gasFees, ); + globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); + await sequencer.initialSync(); await sequencer.work(); expect(proverClient.startNewBlock).toHaveBeenCalledWith( 2, - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); + expect(publisher.processL2Block).toHaveBeenCalledTimes(1); expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(proverClient.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -185,19 +178,20 @@ describe('sequencer', () => { proverClient.startNewBlock.mockResolvedValueOnce(ticket); proverClient.finaliseBlock.mockResolvedValue({ block, aggregationObject: [], proof }); publisher.processL2Block.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + + const mockedGlobalVariables = new GlobalVariables( + chainId, + version, + new Fr(lastBlockNumber + 1), + block.header.globalVariables.slotNumber, + Fr.ZERO, + coinbase, + feeRecipient, + gasFees, ); + globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); + // Not your turn! publisher.isItMyTurnToSubmit.mockClear().mockResolvedValue(false); await sequencer.initialSync(); @@ -209,16 +203,7 @@ describe('sequencer', () => { await sequencer.work(); expect(proverClient.startNewBlock).toHaveBeenCalledWith( 2, - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); @@ -244,19 +229,20 @@ describe('sequencer', () => { proverClient.startNewBlock.mockResolvedValueOnce(ticket); proverClient.finaliseBlock.mockResolvedValue({ block, aggregationObject: [], proof }); publisher.processL2Block.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + + const mockedGlobalVariables = new GlobalVariables( + chainId, + version, + new Fr(lastBlockNumber + 1), + block.header.globalVariables.slotNumber, + Fr.ZERO, + coinbase, + feeRecipient, + gasFees, ); + globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); + // We make a nullifier from tx1 a part of the nullifier tree, so it gets rejected as double spend const doubleSpendNullifier = doubleSpendTx.data.forRollup!.end.nullifiers[0].toBuffer(); merkleTreeOps.findLeafIndex.mockImplementation((treeId: MerkleTreeId, value: any) => { @@ -270,16 +256,7 @@ describe('sequencer', () => { expect(proverClient.startNewBlock).toHaveBeenCalledWith( 2, - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); @@ -306,19 +283,20 @@ describe('sequencer', () => { proverClient.startNewBlock.mockResolvedValueOnce(ticket); proverClient.finaliseBlock.mockResolvedValue({ block, aggregationObject: [], proof }); publisher.processL2Block.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + + const mockedGlobalVariables = new GlobalVariables( + chainId, + version, + new Fr(lastBlockNumber + 1), + block.header.globalVariables.slotNumber, + Fr.ZERO, + coinbase, + feeRecipient, + gasFees, ); + globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); + // We make the chain id on the invalid tx not equal to the configured chain id invalidChainTx.data.constants.txContext.chainId = new Fr(1n + chainId.value); @@ -327,16 +305,7 @@ describe('sequencer', () => { expect(proverClient.startNewBlock).toHaveBeenCalledWith( 2, - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); @@ -362,19 +331,20 @@ describe('sequencer', () => { proverClient.startNewBlock.mockResolvedValueOnce(ticket); proverClient.finaliseBlock.mockResolvedValue({ block, aggregationObject: [], proof }); publisher.processL2Block.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + + const mockedGlobalVariables = new GlobalVariables( + chainId, + version, + new Fr(lastBlockNumber + 1), + block.header.globalVariables.slotNumber, + Fr.ZERO, + coinbase, + feeRecipient, + gasFees, ); + 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); @@ -384,16 +354,7 @@ describe('sequencer', () => { expect(proverClient.startNewBlock).toHaveBeenCalledWith( 2, - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); @@ -416,19 +377,20 @@ describe('sequencer', () => { proverClient.startNewBlock.mockResolvedValueOnce(ticket); proverClient.finaliseBlock.mockResolvedValue({ block, aggregationObject: [], proof }); publisher.processL2Block.mockResolvedValueOnce(true); - globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce( - new GlobalVariables( - chainId, - version, - new Fr(lastBlockNumber + 1), - block.header.globalVariables.slotNumber, - Fr.ZERO, - coinbase, - feeRecipient, - gasFees, - ), + + const mockedGlobalVariables = new GlobalVariables( + chainId, + version, + new Fr(lastBlockNumber + 1), + block.header.globalVariables.slotNumber, + Fr.ZERO, + coinbase, + feeRecipient, + gasFees, ); + globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); + await sequencer.initialSync(); l2BlockSource.getBlockNumber diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 8fbdff27634..98f6fdeb48c 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -231,6 +231,8 @@ export class Sequencer { this._feeRecipient, ); + // @todo @LHerskind Include some logic to consider slots + // TODO: It should be responsibility of the P2P layer to validate txs before passing them on here const allValidTxs = await this.takeValidTxs( pendingTxs, @@ -293,6 +295,8 @@ export class Sequencer { if (!(await this.publisher.isItMyTurnToSubmit())) { throw new Error(`Not this sequencer turn to submit block`); } + + // @todo @LHerskind Should take into account, block number, proposer and slot number }; // Get l1 to l2 messages from the contract