diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 3b4e2b65f662..e37715ccb8a9 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -88,7 +88,11 @@ contract Rollup is Leonidas, IRollup, ITestRollup { VERSION = 1; // Genesis block - blocks[0] = BlockLog({archive: bytes32(0), slotNumber: 0, isProven: true}); + blocks[0] = BlockLog({ + archive: bytes32(0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e), + slotNumber: 0, + isProven: true + }); pendingBlockCount = 1; provenBlockCount = 1; } @@ -526,9 +530,8 @@ contract Rollup is Leonidas, IRollup, ITestRollup { ); } - // 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) { + if (tipArchive != _header.lastArchive.root) { revert Errors.Rollup__InvalidArchive(tipArchive, _header.lastArchive.root); } diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index fc5f57b5d914..cc3cb5ba3890 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -100,7 +100,9 @@ library Constants { uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; uint256 internal constant BLOB_SIZE_IN_BYTES = 126976; uint256 internal constant ETHEREUM_SLOT_DURATION = 12; - uint256 internal constant IS_DEV_NET = 1; + uint256 internal constant AZTEC_SLOT_DURATION = 36; + uint256 internal constant AZTEC_EPOCH_DURATION = 48; + uint256 internal constant IS_DEV_NET = 0; uint256 internal constant FEE_JUICE_INITIAL_MINT = 20000000000; uint256 internal constant MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 20000; uint256 internal constant MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 19be2872e3fb..caab6bce4635 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -83,7 +83,7 @@ library Errors { error Leonidas__EpochNotSetup(); // 0xcf4e597e error Leonidas__InvalidProposer(address expected, address actual); // 0xd02d278e error Leonidas__InsufficientAttestations(uint256 minimumNeeded, uint256 provided); // 0xbf1ca4cb - error Leonidas__InsufficientAttestationsProvided(uint256 minimumNeeded, uint256 provided); // 0x2e7debe9 + error Leonidas__InsufficientAttestationsProvided(uint256 minimumNeeded, uint256 provided); // 0xb3a697c2 // Fee Juice Portal error FeeJuicePortal__AlreadyInitialized(); // 0xc7a172fe diff --git a/l1-contracts/src/core/sequencer_selection/Leonidas.sol b/l1-contracts/src/core/sequencer_selection/Leonidas.sol index 4efdc8ff3cd8..511b49eb622e 100644 --- a/l1-contracts/src/core/sequencer_selection/Leonidas.sol +++ b/l1-contracts/src/core/sequencer_selection/Leonidas.sol @@ -52,12 +52,12 @@ contract Leonidas is Ownable, ILeonidas { // // The value should be a higher multiple for any actual chain // @todo #8019 - uint256 public constant SLOT_DURATION = Constants.ETHEREUM_SLOT_DURATION * 1; + uint256 public constant SLOT_DURATION = Constants.AZTEC_SLOT_DURATION; // The duration of an epoch in slots // @todo @LHerskind - This value should be updated when we are not blind. // @todo #8020 - uint256 public constant EPOCH_DURATION = 32; + uint256 public constant EPOCH_DURATION = Constants.AZTEC_EPOCH_DURATION; // The target number of validators in a committee // @todo #8021 diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index d6f517118589..e931a6ca570e 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -159,6 +159,9 @@ contract RollupTest is DecoderBase { bytes32 archive = data.archive; bytes memory body = data.body; + // Progress time as necessary + vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); + assembly { mstore(add(header, add(0x20, 0x0248)), feeAmount) } @@ -303,6 +306,9 @@ contract RollupTest is DecoderBase { function testBlocksWithAssumeProven() public setUpFor("mixed_block_1") { rollup.setAssumeProvenUntilBlockNumber(2); + assertEq(rollup.pendingBlockCount(), 1, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), 1, "Invalid proven block count"); + _testBlock("mixed_block_1", false); _testBlock("mixed_block_2", false); @@ -311,6 +317,9 @@ contract RollupTest is DecoderBase { } function testSetAssumeProvenAfterBlocksProcessed() public setUpFor("mixed_block_1") { + assertEq(rollup.pendingBlockCount(), 1, "Invalid pending block count"); + assertEq(rollup.provenBlockCount(), 1, "Invalid proven block count"); + _testBlock("mixed_block_1", false); _testBlock("mixed_block_2", false); rollup.setAssumeProvenUntilBlockNumber(2); diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index ef20e7e81544..12b55eb71184 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": "0x0b97584f2e175ce708df94c14fee5e53d1c92cd5308346c6eabb79005ccf6733", + "archive": "0x0f1c8759c5d468bc2923b86ca6489d28a90698c79e7dcab441e5a3bef80a8bea", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -20,12 +20,12 @@ }, "globalVariables": { "blockNumber": 1, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000005", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000031", "chainId": 31337, - "timestamp": 1723460388, + "timestamp": 1724273554, "version": 1, - "coinbase": "0x92c3bc662a41b5406370e6e30b6e4541c9c223e3", - "feeRecipient": "0x2af4d139729812fa69edfc27fc2d19b3d2616c9e4ec2313efb66fb2f234d59da", + "coinbase": "0x15b9be2e7cb33a2fcbb4329e6c5ef65aeffe27e3", + "feeRecipient": "0x01f04e3f96a8bc93bbefcf569bf0e7538d240c089133389702f2fc6c128b8170", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -56,8 +56,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000066b9eb2492c3bc662a41b5406370e6e30b6e4541c9c223e32af4d139729812fa69edfc27fc2d19b3d2616c9e4ec2313efb66fb2f234d59da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00330b9ccec92816ea3dd5fefce65cdb3803cf663cf2959f403501ff1f27a73c", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000100b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000008019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000066c6539215b9be2e7cb33a2fcbb4329e6c5ef65aeffe27e301f04e3f96a8bc93bbefcf569bf0e7538d240c089133389702f2fc6c128b8170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x00f44db060111d0b69ed4305560101aa0b4b2bbe49dba30bcbc59a7f441aa3aa", "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 c45b0a4fc85f..b43dbb44c4f9 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": "0x1d77208270a6eca3c2b56adaad130b28e2fa111d6bc325ce3cc52b6a68f4894f", + "archive": "0x1ff51fd469761e649b7538a6095cdc2ce1510773cabba6920e9883d56c7c4073", "body": "0x00000000", "txsEffectsHash": "0x00e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d6", "decodedHeader": { @@ -20,12 +20,12 @@ }, "globalVariables": { "blockNumber": 2, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000006", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000033", "chainId": 31337, - "timestamp": 1723460400, + "timestamp": 1724273626, "version": 1, - "coinbase": "0x92c3bc662a41b5406370e6e30b6e4541c9c223e3", - "feeRecipient": "0x2af4d139729812fa69edfc27fc2d19b3d2616c9e4ec2313efb66fb2f234d59da", + "coinbase": "0x15b9be2e7cb33a2fcbb4329e6c5ef65aeffe27e3", + "feeRecipient": "0x01f04e3f96a8bc93bbefcf569bf0e7538d240c089133389702f2fc6c128b8170", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x0b97584f2e175ce708df94c14fee5e53d1c92cd5308346c6eabb79005ccf6733" + "root": "0x0f1c8759c5d468bc2923b86ca6489d28a90698c79e7dcab441e5a3bef80a8bea" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,8 +56,8 @@ } } }, - "header": "0x0b97584f2e175ce708df94c14fee5e53d1c92cd5308346c6eabb79005ccf673300000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000066b9eb3092c3bc662a41b5406370e6e30b6e4541c9c223e32af4d139729812fa69edfc27fc2d19b3d2616c9e4ec2313efb66fb2f234d59da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x006ccf0ce5551a2a07b16c10a4b208bd30403231409d44cedac9b6d489b9f212", + "header": "0x0f1c8759c5d468bc2923b86ca6489d28a90698c79e7dcab441e5a3bef80a8bea00000002000000000000000000000000000000000000000000000000000000000000000200e994e16b3763fd5039413cf99c2b3c378e2bab939e7992a77bd201b28160d600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb14f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000200b59baa35b9dc267744f0ccb4e3b0255c1fc512460d91130c6bc19fb2668568d0000010019a8c197c12bb33da6314c4ef4f8f6fcb9e25250c085df8672adf67c8f1e3dbc0000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000066c653da15b9be2e7cb33a2fcbb4329e6c5ef65aeffe27e301f04e3f96a8bc93bbefcf569bf0e7538d240c089133389702f2fc6c128b8170000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x001d78131989b826aabf44621ab134c2eb31c676c72a3936295a37b36ce609a5", "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 ee676dee4ca6..0c870c257f30 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": "0x0f16cd5260bfdd24b99a5aa4fd778c58f4348f57e5c9697bde3f2ec56a026d56", + "archive": "0x04a29a249d47adf5edb82a074578f57523868c28f83f86a39382ea0d66fc7c0b", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f0000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000017100000000000000000000000000000000000000000000000000000000000001720000000000000000000000000000000000000000000000000000000000000173000000000000000000000000000000000000000000000000000000000000017400000000000000000000000000000000000000000000000000000000000001750000000000000000000000000000000000000000000000000000000000000176000000000000000000000000000000000000000000000000000000000000017700000000000000000000000000000000000000000000000000000000000001780000000000000000000000000000000000000000000000000000000000000179000000000000000000000000000000000000000000000000000000000000017a000000000000000000000000000000000000000000000000000000000000017b000000000000000000000000000000000000000000000000000000000000017c000000000000000000000000000000000000000000000000000000000000017d000000000000000000000000000000000000000000000000000000000000017e000000000000000000000000000000000000000000000000000000000000017f3f0000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e0800c47667396742a5474f325e2567bff3bb99b7f0bfd2b1a689b635d8b8726cce00284120278895e8d47084ae759f390e9634881e41369a257a36fe99a2369dc800a328b4a4a6ed156325253b4ab2af7ca00e21caf7963f0fba8a88ccdc3512c300705c99df420bface231f6855799db1d0ed7d39419abc47aa8c6efe2ae7aae2009299cc308de6d23788384411e024791a5b2448e455fbdd1d1f28f3ff76631f002d6c03d81ad764de51b0f34584645191cdc2aaae2ca08fb838d142b95d62f5003032f3618b2df0fa335d5fd548d6d85e42b4e7eb5fff9eb687facbbdecb8a60016cab7ddf4d1b440d53d10284c5c82a78b2d4e27dcdb44ef434ef4c6bad6783f0000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000551000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000552000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005560000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000055700000000000000000000000000000000000000000000000000000000000005610000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000056200000000000000000000000000000000000000000000000000000000000005590000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000055a0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000055b0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000055c0000000000000000000000000000000000000000000000000000000000000566000000000000000000000000000000000000000000000000000000000000055d0000000000000000000000000000000000000000000000000000000000000567000000000000000000000000000000000000000000000000000000000000055e0000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000055f00000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000560000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000561000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000562000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000563000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000564000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000565000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005660000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000056700000000000000000000000000000000000000000000000000000000000005710000000000000000000000000000000000000000000000000000000000000568000000000000000000000000000000000000000000000000000000000000057200000000000000000000000000000000000000000000000000000000000005690000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000056a0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000056b0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000056c0000000000000000000000000000000000000000000000000000000000000576000000000000000000000000000000000000000000000000000000000000056d0000000000000000000000000000000000000000000000000000000000000577000000000000000000000000000000000000000000000000000000000000056e0000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000056f00000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000570000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000571000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000572000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000573000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000574000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000575000000000000000000000000000000000000000000000000000000000000057f00000000000000000000000000000000000000000000000000000000000005760000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000057700000000000000000000000000000000000000000000000000000000000005810000000000000000000000000000000000000000000000000000000000000578000000000000000000000000000000000000000000000000000000000000058200000000000000000000000000000000000000000000000000000000000005790000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000057a0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000057b0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000057c0000000000000000000000000000000000000000000000000000000000000586000000000000000000000000000000000000000000000000000000000000057d0000000000000000000000000000000000000000000000000000000000000587000000000000000000000000000000000000000000000000000000000000057e0000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b700000000000000000000000000000000000000000000000000000000000001b800000000000000000000000000000000000000000000000000000000000001b900000000000000000000000000000000000000000000000000000000000001ba00000000000000000000000000000000000000000000000000000000000001bb00000000000000000000000000000000000000000000000000000000000001bc00000000000000000000000000000000000000000000000000000000000001bd00000000000000000000000000000000000000000000000000000000000001be00000000000000000000000000000000000000000000000000000000000001bf3f0000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be0800789ff73d7787206612d96dfc2143f2344de21669a3f8cae7fe9a8918631eb00084a17f00bf8793b6851a106e9155543125e0be987ad3c8334456bdda171d0b00a400f8fd336ad84f467465964008238fd1b7f9c51c22912d706cd2b874d24e002c79bdd83c14ff50a46964f838ee207564909e28af79a57fc195810d36f9b20070083c6ef1e4dd88a064e94d2582283b203cf8a2ab1667f4370eda1b4c1fe8005373dffb5b590053d7762efcf9e11280f1486ce82e7996d94ee0f5d7c093bc009eefd90eb40e79c78bac1f71ec78bdc2f8b30041974239bdc765edffed813800ea95742e72792ca7a0f66ce9f55bc47dc09d5ea08c1b9018763102776978303f0000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005990000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000059a0000000000000000000000000000000000000000000000000000000000000591000000000000000000000000000000000000000000000000000000000000059b0000000000000000000000000000000000000000000000000000000000000592000000000000000000000000000000000000000000000000000000000000059c0000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000059d0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000059e0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000059f000000000000000000000000000000000000000000000000000000000000059600000000000000000000000000000000000000000000000000000000000005a0000000000000000000000000000000000000000000000000000000000000059700000000000000000000000000000000000000000000000000000000000005a1000000000000000000000000000000000000000000000000000000000000059800000000000000000000000000000000000000000000000000000000000005a2000000000000000000000000000000000000000000000000000000000000059900000000000000000000000000000000000000000000000000000000000005a3000000000000000000000000000000000000000000000000000000000000059a00000000000000000000000000000000000000000000000000000000000005a4000000000000000000000000000000000000000000000000000000000000059b00000000000000000000000000000000000000000000000000000000000005a5000000000000000000000000000000000000000000000000000000000000059c00000000000000000000000000000000000000000000000000000000000005a6000000000000000000000000000000000000000000000000000000000000059d00000000000000000000000000000000000000000000000000000000000005a7000000000000000000000000000000000000000000000000000000000000059e00000000000000000000000000000000000000000000000000000000000005a8000000000000000000000000000000000000000000000000000000000000059f00000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005a000000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005a100000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005a200000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005a300000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005a400000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005a500000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005a600000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005a700000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005a800000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005a900000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005aa00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005ab00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005ac00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005ad00000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005ae00000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005af00000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005b000000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005b100000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005b200000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005b300000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005b400000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005b500000000000000000000000000000000000000000000000000000000000005bf00000000000000000000000000000000000000000000000000000000000005b600000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005b700000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005b800000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005b900000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005ba00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005bb00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005bc00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005bd00000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005be00000000000000000000000000000000000000000000000000000000000005c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f700000000000000000000000000000000000000000000000000000000000001f800000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001fa00000000000000000000000000000000000000000000000000000000000001fb00000000000000000000000000000000000000000000000000000000000001fc00000000000000000000000000000000000000000000000000000000000001fd00000000000000000000000000000000000000000000000000000000000001fe00000000000000000000000000000000000000000000000000000000000001ff3f00000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe0800a68d2df6e48c8b31f4c76529e586de2cd9d0f2f2fdfbc4c523db9e3a29e9b80016c236e57bf17afe324437acd1060772e3f31d4f9e734ad758d0627c4ba2a200d659011ddde95e32886bdd8c9464da1ca144ccadd539f0992b4abb491d812a00c8025bb9006a976ebd6ad940155f15f89ca0bb7312b53841fc257e7ed689c8004165f2c46b70fb183468b38f31bba7aa9d22ce8dfb61fe721470729ce1c6b100afeb60dd983514ebbaee141b2196f3eb3c9c299f576a0097872cc85a79a43f005f6bfee53d20a474901493558419dbceb3aca40e5e18915d38031498f4d2bb008791217ee341ec5dc11f7d7a31160fb1b1f2cf767062970e9526e5751956253f00000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005d900000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005da00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005db00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005dc00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005dd00000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005de00000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005df00000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005e100000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005e200000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005e300000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005e400000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005e500000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005e600000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005e700000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005e800000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005e900000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005ea00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005eb00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ec00000000000000000000000000000000000000000000000000000000000005f600000000000000000000000000000000000000000000000000000000000005ed00000000000000000000000000000000000000000000000000000000000005f700000000000000000000000000000000000000000000000000000000000005ee00000000000000000000000000000000000000000000000000000000000005f800000000000000000000000000000000000000000000000000000000000005ef00000000000000000000000000000000000000000000000000000000000005f900000000000000000000000000000000000000000000000000000000000005f000000000000000000000000000000000000000000000000000000000000005fa00000000000000000000000000000000000000000000000000000000000005f100000000000000000000000000000000000000000000000000000000000005fb00000000000000000000000000000000000000000000000000000000000005f200000000000000000000000000000000000000000000000000000000000005fc00000000000000000000000000000000000000000000000000000000000005f300000000000000000000000000000000000000000000000000000000000005fd00000000000000000000000000000000000000000000000000000000000005f400000000000000000000000000000000000000000000000000000000000005fe00000000000000000000000000000000000000000000000000000000000005f500000000000000000000000000000000000000000000000000000000000005ff00000000000000000000000000000000000000000000000000000000000005f6000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000005f7000000000000000000000000000000000000000000000000000000000000060100000000000000000000000000000000000000000000000000000000000005f8000000000000000000000000000000000000000000000000000000000000060200000000000000000000000000000000000000000000000000000000000005f9000000000000000000000000000000000000000000000000000000000000060300000000000000000000000000000000000000000000000000000000000005fa000000000000000000000000000000000000000000000000000000000000060400000000000000000000000000000000000000000000000000000000000005fb000000000000000000000000000000000000000000000000000000000000060500000000000000000000000000000000000000000000000000000000000005fc000000000000000000000000000000000000000000000000000000000000060600000000000000000000000000000000000000000000000000000000000005fd000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000005fe0000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f0000000000000000000000000000000000000000000000000000000000000230000000000000000000000000000000000000000000000000000000000000023100000000000000000000000000000000000000000000000000000000000002320000000000000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000023400000000000000000000000000000000000000000000000000000000000002350000000000000000000000000000000000000000000000000000000000000236000000000000000000000000000000000000000000000000000000000000023700000000000000000000000000000000000000000000000000000000000002380000000000000000000000000000000000000000000000000000000000000239000000000000000000000000000000000000000000000000000000000000023a000000000000000000000000000000000000000000000000000000000000023b000000000000000000000000000000000000000000000000000000000000023c000000000000000000000000000000000000000000000000000000000000023d000000000000000000000000000000000000000000000000000000000000023e000000000000000000000000000000000000000000000000000000000000023f3f0000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e0800c064a9343bfaf1345a5ad188e96aa4c5bad0b4a5590da51a9ff8f3c98ade8d008803d57dd0923c95a01b2bfbee4df6d66dc7baee1d2cd2770575feb86d040200ea64eed9489feb7bdf29bf817a6e8772e549da7b291028852d0dd3810cee9500947e8f904d41be8a4e08b146b4e1f0cd88f55722ef987d1d485c4196ab9f71002e5d9ed5d71bc3bea6edf988c4b9ba7fceb0815180d893852ed343c64ab55c0040f7f519ec89d360d83e242b6c0ce049d2b3356b8cfbf1ff3b733ef0f8a089006f5cfe5fc4a7b87c634f9e253a7cea2052229250d0c0e913eb50b5ef3612de00b759fce0eed36bb653b67255cce111b3529c383bd7d2b758f8cb53a4451f273f0000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000611000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000612000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006160000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000061700000000000000000000000000000000000000000000000000000000000006210000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000062200000000000000000000000000000000000000000000000000000000000006190000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000061a0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000061b0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000061c0000000000000000000000000000000000000000000000000000000000000626000000000000000000000000000000000000000000000000000000000000061d0000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000061e0000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000061f00000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000621000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000622000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000623000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000624000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000625000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006260000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000062700000000000000000000000000000000000000000000000000000000000006310000000000000000000000000000000000000000000000000000000000000628000000000000000000000000000000000000000000000000000000000000063200000000000000000000000000000000000000000000000000000000000006290000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000062a0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000062b0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000062c0000000000000000000000000000000000000000000000000000000000000636000000000000000000000000000000000000000000000000000000000000062d0000000000000000000000000000000000000000000000000000000000000637000000000000000000000000000000000000000000000000000000000000062e0000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000062f00000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000630000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000631000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000632000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000633000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000634000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000635000000000000000000000000000000000000000000000000000000000000063f00000000000000000000000000000000000000000000000000000000000006360000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000063700000000000000000000000000000000000000000000000000000000000006410000000000000000000000000000000000000000000000000000000000000638000000000000000000000000000000000000000000000000000000000000064200000000000000000000000000000000000000000000000000000000000006390000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000063a0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000063b0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000063c0000000000000000000000000000000000000000000000000000000000000646000000000000000000000000000000000000000000000000000000000000063d0000000000000000000000000000000000000000000000000000000000000647000000000000000000000000000000000000000000000000000000000000063e0000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x00e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b", "decodedHeader": { @@ -70,12 +70,12 @@ }, "globalVariables": { "blockNumber": 1, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000015", + "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000036", "chainId": 31337, - "timestamp": 1723460076, + "timestamp": 1724271382, "version": 1, - "coinbase": "0x626f9afff6e3b189ec5e445c51dc49adfeb76787", - "feeRecipient": "0x3006484f89d6047e247437886aadc397f0e95715967c3b28802a79b7c176171f", + "coinbase": "0xa9d34da1b127b355094c0b05e1c6823bc8f03f32", + "feeRecipient": "0x07dc0165328a32abad910b7e6f2c002e73770faed93552332c48b91cb0c2839b", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -106,8 +106,8 @@ } } }, - "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000066b9e9ec626f9afff6e3b189ec5e445c51dc49adfeb767873006484f89d6047e247437886aadc397f0e95715967c3b28802a79b7c176171f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00527b3ec43d9c93df7272603b7d6381e2438c958fa7f901c499e44fde448f02", + "header": "0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e00000001000000000000000000000000000000000000000000000000000000000000000400e7daa0660d17d3ae04747bd24c7238da34e77cb04b0b9dd2843dd08f0fd87b00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00d0169cc64b8f1bd695ec8611a5602da48854dc4cc04989c4b63288b339cb1814f44d672eb357739e42463497f9fdac46623af863eea4d947ca00a497dcdeb3000000101a995cda6f326074cf650c6644269e29dbd0532e6a832238345b53ee70c878af000001000deac8396e31bc1196b442ad724bf8f751a245e518147d738cc84b9e1a56b4420000018023866f4c16f3ea1f37dd2ca42d1a635ea909b6c016e45e8434780d3741eb7dbb000001800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000066c64b16a9d34da1b127b355094c0b05e1c6823bc8f03f3207dc0165328a32abad910b7e6f2c002e73770faed93552332c48b91cb0c2839b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0019d429ff2f434d153bd0ba75ec86753950f52e56638d755d1ee12cc56b8dd1", "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 666859288b0f..b36d873042f4 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": "0x134870d4e66a9ef122ee79c14ef6f75c9b34a63fd337a86c3a3ea27b5d08e10a", + "archive": "0x0e5cb6172dd7267dee1a9a852391fa9e92f4ab64f4f10cf5cb6f3b0c7f7c5181", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f0000000000000000000000000000000000000000000000000000000000000270000000000000000000000000000000000000000000000000000000000000027100000000000000000000000000000000000000000000000000000000000002720000000000000000000000000000000000000000000000000000000000000273000000000000000000000000000000000000000000000000000000000000027400000000000000000000000000000000000000000000000000000000000002750000000000000000000000000000000000000000000000000000000000000276000000000000000000000000000000000000000000000000000000000000027700000000000000000000000000000000000000000000000000000000000002780000000000000000000000000000000000000000000000000000000000000279000000000000000000000000000000000000000000000000000000000000027a000000000000000000000000000000000000000000000000000000000000027b000000000000000000000000000000000000000000000000000000000000027c000000000000000000000000000000000000000000000000000000000000027d000000000000000000000000000000000000000000000000000000000000027e000000000000000000000000000000000000000000000000000000000000027f3f0000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f0000000000000000000000000000000000000000000000000000000000000370000000000000000000000000000000000000000000000000000000000000037100000000000000000000000000000000000000000000000000000000000003720000000000000000000000000000000000000000000000000000000000000373000000000000000000000000000000000000000000000000000000000000037400000000000000000000000000000000000000000000000000000000000003750000000000000000000000000000000000000000000000000000000000000376000000000000000000000000000000000000000000000000000000000000037700000000000000000000000000000000000000000000000000000000000003780000000000000000000000000000000000000000000000000000000000000379000000000000000000000000000000000000000000000000000000000000037a000000000000000000000000000000000000000000000000000000000000037b000000000000000000000000000000000000000000000000000000000000037c000000000000000000000000000000000000000000000000000000000000037d000000000000000000000000000000000000000000000000000000000000037e08003bbb1177505f3433bb062787fcac6585d30fa1a7e0b809ca5eef1cecc56cd0002d5b86280022d106b72e4425ea49f927ca2b8138fc13b3d9feeaf36ae61fb100adab9d66b73ae23a6e9127ebe0bcd963ef4312dd66878a6be131d39a7ee01c00d48f30dbb82c96c734c8abe33f4f9f75e6d0ba4462ee07d73c5335e04a02e900f31a3a4e7333ac6043a929fca12f5347e9e8bf1d67f5993860a774f10b77bc00230e3132bfa5df23e2e018b20cd4e0c75555825ee7924da73f017a279d39cd0095e2affd6b67c6ecbf77fa1e638139498e1642abb468c58ca8ce275260ea6100362e0941035fd171fab926caf55d18b22f7de99d60ac6f454386a9cce4a1ff3f0000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000651000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000652000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006560000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000065700000000000000000000000000000000000000000000000000000000000006610000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000066200000000000000000000000000000000000000000000000000000000000006590000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000065a0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000065b0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000065c0000000000000000000000000000000000000000000000000000000000000666000000000000000000000000000000000000000000000000000000000000065d0000000000000000000000000000000000000000000000000000000000000667000000000000000000000000000000000000000000000000000000000000065e0000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000065f00000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000661000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000662000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000663000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000664000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000665000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006660000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000066700000000000000000000000000000000000000000000000000000000000006710000000000000000000000000000000000000000000000000000000000000668000000000000000000000000000000000000000000000000000000000000067200000000000000000000000000000000000000000000000000000000000006690000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000066a0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000066b0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000066c0000000000000000000000000000000000000000000000000000000000000676000000000000000000000000000000000000000000000000000000000000066d0000000000000000000000000000000000000000000000000000000000000677000000000000000000000000000000000000000000000000000000000000066e0000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000066f00000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000670000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000671000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000672000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000673000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000674000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000675000000000000000000000000000000000000000000000000000000000000067f00000000000000000000000000000000000000000000000000000000000006760000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000067700000000000000000000000000000000000000000000000000000000000006810000000000000000000000000000000000000000000000000000000000000678000000000000000000000000000000000000000000000000000000000000068200000000000000000000000000000000000000000000000000000000000006790000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000067a0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000067b0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000067c0000000000000000000000000000000000000000000000000000000000000686000000000000000000000000000000000000000000000000000000000000067d0000000000000000000000000000000000000000000000000000000000000687000000000000000000000000000000000000000000000000000000000000067e0000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b700000000000000000000000000000000000000000000000000000000000002b800000000000000000000000000000000000000000000000000000000000002b900000000000000000000000000000000000000000000000000000000000002ba00000000000000000000000000000000000000000000000000000000000002bb00000000000000000000000000000000000000000000000000000000000002bc00000000000000000000000000000000000000000000000000000000000002bd00000000000000000000000000000000000000000000000000000000000002be00000000000000000000000000000000000000000000000000000000000002bf3f0000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b600000000000000000000000000000000000000000000000000000000000003b700000000000000000000000000000000000000000000000000000000000003b800000000000000000000000000000000000000000000000000000000000003b900000000000000000000000000000000000000000000000000000000000003ba00000000000000000000000000000000000000000000000000000000000003bb00000000000000000000000000000000000000000000000000000000000003bc00000000000000000000000000000000000000000000000000000000000003bd00000000000000000000000000000000000000000000000000000000000003be08004a32502b5d2a0cf5d776c92ef74de61a28e7882bdadeb3b0530f472704604300808c2412e2725ecaa6a6bd77e3159349e238dc7817f906ba32afd40b3cb3cb00d7d4e3b313c4cce9bd98c317ea715847a92d795b82a6f8b8144b7c61bee64200b76f07678c289f41378029b1353a73e1afbe241612a97c23e7fc059099f49d00c72046b39a9dc902cee36db5214c72315636bd824abfabdf80b1c5e6a01fd7006e0a74fec166a12f5a62954776784f01cba3be7ab876eef2e49a2ab7a5b0f900c83ddd8f6b91086bc83485adbe8056212b4d33b91840cd3dc649f9736881460022441e76225010acce7f429dc754fb3260ae1d387937978f69c67a879ed0733f0000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006990000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000069a0000000000000000000000000000000000000000000000000000000000000691000000000000000000000000000000000000000000000000000000000000069b0000000000000000000000000000000000000000000000000000000000000692000000000000000000000000000000000000000000000000000000000000069c0000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000069d0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000069e0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000069f000000000000000000000000000000000000000000000000000000000000069600000000000000000000000000000000000000000000000000000000000006a0000000000000000000000000000000000000000000000000000000000000069700000000000000000000000000000000000000000000000000000000000006a1000000000000000000000000000000000000000000000000000000000000069800000000000000000000000000000000000000000000000000000000000006a2000000000000000000000000000000000000000000000000000000000000069900000000000000000000000000000000000000000000000000000000000006a3000000000000000000000000000000000000000000000000000000000000069a00000000000000000000000000000000000000000000000000000000000006a4000000000000000000000000000000000000000000000000000000000000069b00000000000000000000000000000000000000000000000000000000000006a5000000000000000000000000000000000000000000000000000000000000069c00000000000000000000000000000000000000000000000000000000000006a6000000000000000000000000000000000000000000000000000000000000069d00000000000000000000000000000000000000000000000000000000000006a7000000000000000000000000000000000000000000000000000000000000069e00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000069f00000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006a000000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a100000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006a200000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006a300000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006a400000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006a500000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006a600000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006a700000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006a800000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006a900000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006ab00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006ac00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006ad00000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006ae00000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006af00000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006b000000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006b100000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006b200000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006b300000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006b400000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006b500000000000000000000000000000000000000000000000000000000000006bf00000000000000000000000000000000000000000000000000000000000006b600000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006b700000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006b800000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006b900000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006ba00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006bb00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006bc00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006bd00000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006be00000000000000000000000000000000000000000000000000000000000006c80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f700000000000000000000000000000000000000000000000000000000000002f800000000000000000000000000000000000000000000000000000000000002f900000000000000000000000000000000000000000000000000000000000002fa00000000000000000000000000000000000000000000000000000000000002fb00000000000000000000000000000000000000000000000000000000000002fc00000000000000000000000000000000000000000000000000000000000002fd00000000000000000000000000000000000000000000000000000000000002fe00000000000000000000000000000000000000000000000000000000000002ff3f00000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f600000000000000000000000000000000000000000000000000000000000003f700000000000000000000000000000000000000000000000000000000000003f800000000000000000000000000000000000000000000000000000000000003f900000000000000000000000000000000000000000000000000000000000003fa00000000000000000000000000000000000000000000000000000000000003fb00000000000000000000000000000000000000000000000000000000000003fc00000000000000000000000000000000000000000000000000000000000003fd00000000000000000000000000000000000000000000000000000000000003fe0800bb07f923e24c36227d717557d58d32b99370b81f7a70d1835becc1114f7d7700624291eff6ab801e5668bc6619a3df132f8b392b063f09dfe8a69e38224eb200bd6b195f8716ab3dc93c44037cac579d25d0e77c2782b5aa62534ee25d36bc008c99d470d2c53624a8c5bedfeffdcc5356f6da89ee0e372b3ea3fa4f8cd652009944e00a3f9a7d2e8a535d3a210c3271d5732518037704d67ef5d42a8b82c200523014cb6eabe4366c6e599ba96534fc15ecc804a13fbaaacf8717e1b0a8d20005621252c4b36c113f21ad6c13b99e5cef514bdd98ef0aae4075b5cb5a000a00d80cb2a60aae6c3d2e7d27fb1519a708a18bb5b5085f78684bdee7512856a93f00000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006d900000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006da00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006db00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006dc00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006dd00000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006de00000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006df00000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006e000000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006e100000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006e200000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006e300000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006e400000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006e500000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006e600000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006e700000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006e800000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006e900000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006ea00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006eb00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ec00000000000000000000000000000000000000000000000000000000000006f600000000000000000000000000000000000000000000000000000000000006ed00000000000000000000000000000000000000000000000000000000000006f700000000000000000000000000000000000000000000000000000000000006ee00000000000000000000000000000000000000000000000000000000000006f800000000000000000000000000000000000000000000000000000000000006ef00000000000000000000000000000000000000000000000000000000000006f900000000000000000000000000000000000000000000000000000000000006f000000000000000000000000000000000000000000000000000000000000006fa00000000000000000000000000000000000000000000000000000000000006f100000000000000000000000000000000000000000000000000000000000006fb00000000000000000000000000000000000000000000000000000000000006f200000000000000000000000000000000000000000000000000000000000006fc00000000000000000000000000000000000000000000000000000000000006f300000000000000000000000000000000000000000000000000000000000006fd00000000000000000000000000000000000000000000000000000000000006f400000000000000000000000000000000000000000000000000000000000006fe00000000000000000000000000000000000000000000000000000000000006f500000000000000000000000000000000000000000000000000000000000006ff00000000000000000000000000000000000000000000000000000000000006f6000000000000000000000000000000000000000000000000000000000000070000000000000000000000000000000000000000000000000000000000000006f7000000000000000000000000000000000000000000000000000000000000070100000000000000000000000000000000000000000000000000000000000006f8000000000000000000000000000000000000000000000000000000000000070200000000000000000000000000000000000000000000000000000000000006f9000000000000000000000000000000000000000000000000000000000000070300000000000000000000000000000000000000000000000000000000000006fa000000000000000000000000000000000000000000000000000000000000070400000000000000000000000000000000000000000000000000000000000006fb000000000000000000000000000000000000000000000000000000000000070500000000000000000000000000000000000000000000000000000000000006fc000000000000000000000000000000000000000000000000000000000000070600000000000000000000000000000000000000000000000000000000000006fd000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000006fe0000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f0000000000000000000000000000000000000000000000000000000000000330000000000000000000000000000000000000000000000000000000000000033100000000000000000000000000000000000000000000000000000000000003320000000000000000000000000000000000000000000000000000000000000333000000000000000000000000000000000000000000000000000000000000033400000000000000000000000000000000000000000000000000000000000003350000000000000000000000000000000000000000000000000000000000000336000000000000000000000000000000000000000000000000000000000000033700000000000000000000000000000000000000000000000000000000000003380000000000000000000000000000000000000000000000000000000000000339000000000000000000000000000000000000000000000000000000000000033a000000000000000000000000000000000000000000000000000000000000033b000000000000000000000000000000000000000000000000000000000000033c000000000000000000000000000000000000000000000000000000000000033d000000000000000000000000000000000000000000000000000000000000033e000000000000000000000000000000000000000000000000000000000000033f3f0000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f0000000000000000000000000000000000000000000000000000000000000430000000000000000000000000000000000000000000000000000000000000043100000000000000000000000000000000000000000000000000000000000004320000000000000000000000000000000000000000000000000000000000000433000000000000000000000000000000000000000000000000000000000000043400000000000000000000000000000000000000000000000000000000000004350000000000000000000000000000000000000000000000000000000000000436000000000000000000000000000000000000000000000000000000000000043700000000000000000000000000000000000000000000000000000000000004380000000000000000000000000000000000000000000000000000000000000439000000000000000000000000000000000000000000000000000000000000043a000000000000000000000000000000000000000000000000000000000000043b000000000000000000000000000000000000000000000000000000000000043c000000000000000000000000000000000000000000000000000000000000043d000000000000000000000000000000000000000000000000000000000000043e0800a38df4d53fe5da3d48c97dd0f58e7a52faade40c8f50bc0f6408a2b5b3829800a3d4b994758c6630518cce3116391874b9b3b8a1bbcb36485d2702f05af359004c06e9dd14418667d7c66384699665f9222ed08be87c67293a2f1b6b4c41aa006b77b11703f0e3d21aa68c9f6d2ae8ad94ecafdb56be0c4605a0c6723e9ddc0049a087e215b640d8360f8dd98e07c77e4d2025a0dcdcaf78bc00bd6fde09680014741a52013a10622de90b1a7854f1203af5c97121a4b3774c249fba6e0dba00c783bd01c4a4cafe83fd3b4d1ce0c555be4b6d1f772cccccf86049f9af0bbe002ff3ac4d7e2f1caf1fb30e1d20eba5be2b6a42dd54690dee988a934026491e3f0000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000711000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000712000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007160000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000071700000000000000000000000000000000000000000000000000000000000007210000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000072200000000000000000000000000000000000000000000000000000000000007190000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000071a0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000071b0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000071c0000000000000000000000000000000000000000000000000000000000000726000000000000000000000000000000000000000000000000000000000000071d0000000000000000000000000000000000000000000000000000000000000727000000000000000000000000000000000000000000000000000000000000071e0000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000071f00000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000720000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000721000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000722000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000723000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000724000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000725000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007260000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000072700000000000000000000000000000000000000000000000000000000000007310000000000000000000000000000000000000000000000000000000000000728000000000000000000000000000000000000000000000000000000000000073200000000000000000000000000000000000000000000000000000000000007290000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000072a0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000072b0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000072c0000000000000000000000000000000000000000000000000000000000000736000000000000000000000000000000000000000000000000000000000000072d0000000000000000000000000000000000000000000000000000000000000737000000000000000000000000000000000000000000000000000000000000072e0000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000072f00000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000730000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000731000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000732000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000733000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000734000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000735000000000000000000000000000000000000000000000000000000000000073f00000000000000000000000000000000000000000000000000000000000007360000000000000000000000000000000000000000000000000000000000000740000000000000000000000000000000000000000000000000000000000000073700000000000000000000000000000000000000000000000000000000000007410000000000000000000000000000000000000000000000000000000000000738000000000000000000000000000000000000000000000000000000000000074200000000000000000000000000000000000000000000000000000000000007390000000000000000000000000000000000000000000000000000000000000743000000000000000000000000000000000000000000000000000000000000073a0000000000000000000000000000000000000000000000000000000000000744000000000000000000000000000000000000000000000000000000000000073b0000000000000000000000000000000000000000000000000000000000000745000000000000000000000000000000000000000000000000000000000000073c0000000000000000000000000000000000000000000000000000000000000746000000000000000000000000000000000000000000000000000000000000073d0000000000000000000000000000000000000000000000000000000000000747000000000000000000000000000000000000000000000000000000000000073e0000000000000000000000000000000000000000000000000000000000000748000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd646", "decodedHeader": { @@ -70,12 +70,12 @@ }, "globalVariables": { "blockNumber": 2, - "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000026", + "slotNumber": "0x000000000000000000000000000000000000000000000000000000000000003d", "chainId": 31337, - "timestamp": 1723460280, + "timestamp": 1724271634, "version": 1, - "coinbase": "0x626f9afff6e3b189ec5e445c51dc49adfeb76787", - "feeRecipient": "0x3006484f89d6047e247437886aadc397f0e95715967c3b28802a79b7c176171f", + "coinbase": "0xa9d34da1b127b355094c0b05e1c6823bc8f03f32", + "feeRecipient": "0x07dc0165328a32abad910b7e6f2c002e73770faed93552332c48b91cb0c2839b", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -83,7 +83,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x0f16cd5260bfdd24b99a5aa4fd778c58f4348f57e5c9697bde3f2ec56a026d56" + "root": "0x04a29a249d47adf5edb82a074578f57523868c28f83f86a39382ea0d66fc7c0b" }, "stateReference": { "l1ToL2MessageTree": { @@ -106,8 +106,8 @@ } } }, - "header": "0x0f16cd5260bfdd24b99a5aa4fd778c58f4348f57e5c9697bde3f2ec56a026d56000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000066b9eab8626f9afff6e3b189ec5e445c51dc49adfeb767873006484f89d6047e247437886aadc397f0e95715967c3b28802a79b7c176171f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x004eda0b54627380c070bcc54fec28054dc20d47285a458a30c9159eba44a2ad", + "header": "0x04a29a249d47adf5edb82a074578f57523868c28f83f86a39382ea0d66fc7c0b000000020000000000000000000000000000000000000000000000000000000000000004008e46703a73fee39cb8a1bd50a03e090eb250de227639bbf1448462452bd64600212ff46db74e06c26240f9a92fb6fea84709380935d657361bbd5bcb89193700d4b436f0c9857646ed7cf0836bd61c857183956d1acefe52fc99ef7b333a38224c43ed89fb9404e06e7382170d1e279a53211bab61876f38d8a4180390b7ad0000002017752a4346cf34b18277458ace73be4895316cb1c3cbce628d573d5d10cde7ce00000200152db065a479b5630768d6c5250bb6233e71729f857c16cffa98569acf90a2bf000002800a020b31737a919cbd6b0c0fe25d466a11e2186eb8038cd63a5e7d2900473d53000002800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000003d0000000000000000000000000000000000000000000000000000000066c64c12a9d34da1b127b355094c0b05e1c6823bc8f03f3207dc0165328a32abad910b7e6f2c002e73770faed93552332c48b91cb0c2839b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x0087a0c6c632e6707d4de8f51cd648b6085625fce2ef3d59076ed1b1af7227ec", "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 01b36aa665df..01f49c5a2bf8 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -109,12 +109,9 @@ contract SpartaTest is DecoderBase { } 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 - - 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, ts); // We need signatures! + + _testBlock("mixed_block_1", _insufficientSigs, committeSize, false); assertEq( rollup.getEpochCommittee(rollup.getCurrentEpoch()).length, @@ -128,7 +125,7 @@ contract SpartaTest is DecoderBase { return; } - _testBlock("mixed_block_1", false, 0, false); // We run a block before the epoch with validators + _testBlock("mixed_block_1", false, 3, false); // We run a block before the epoch with validators _testBlock("mixed_block_2", false, 3, false); // We need signatures! } @@ -137,8 +134,7 @@ contract SpartaTest is DecoderBase { return; } - _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! + _testBlock("mixed_block_1", true, 3, true); } function testInsufficientSigs() public setup(4) { @@ -146,8 +142,7 @@ contract SpartaTest is DecoderBase { return; } - _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! + _testBlock("mixed_block_1", true, 2, false); } struct StructToAvoidDeepStacks { @@ -161,16 +156,6 @@ contract SpartaTest is DecoderBase { bool _expectRevert, uint256 _signatureCount, bool _invalidaProposer - ) 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; @@ -180,18 +165,7 @@ 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, 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) - } - } + vm.warp(max(block.timestamp, full.block.decodedHeader.globalVariables.timestamp)); _populateInbox(full.populate.sender, full.populate.recipient, full.populate.l1ToL2Content); @@ -248,7 +222,7 @@ contract SpartaTest is DecoderBase { rollup.process(header, archive); } - assertEq(_expectRevert, ree.shouldRevert, "Invalid revert expectation"); + assertEq(_expectRevert, ree.shouldRevert, "Does not match revert expectation"); bytes32 l2ToL1MessageTreeRoot; { 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 cf082ee91ff7..6a3f13e020f1 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -132,8 +132,10 @@ 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; -global IS_DEV_NET: bool = true; -// The following and the value in `deploy_l1_contracts´ must match. We should not have the code both places, but +global AZTEC_SLOT_DURATION: u32 = ETHEREUM_SLOT_DURATION * 3; +global AZTEC_EPOCH_DURATION: u32 = 48; +global IS_DEV_NET: bool = false; +// The following and the value in `deploy_l1_contracts´ must match. We should not have the code both places, but // we are running into circular dependency issues. #3342 global FEE_JUICE_INITIAL_MINT: Field = 20000000000; diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index 4943d1fd7643..8d90cfac636a 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -86,7 +86,9 @@ export const INITIALIZATION_SLOT_SEPARATOR = 1000000000; export const INITIAL_L2_BLOCK_NUM = 1; export const BLOB_SIZE_IN_BYTES = 126976; export const ETHEREUM_SLOT_DURATION = 12; -export const IS_DEV_NET = 1; +export const AZTEC_SLOT_DURATION = 36; +export const AZTEC_EPOCH_DURATION = 48; +export const IS_DEV_NET = 0; export const FEE_JUICE_INITIAL_MINT = 20000000000; export const MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS = 20000; export const MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS = 3000; diff --git a/yarn-project/end-to-end/package.json b/yarn-project/end-to-end/package.json index 98d1e156cd4c..e1bdd04b3389 100644 --- a/yarn-project/end-to-end/package.json +++ b/yarn-project/end-to-end/package.json @@ -15,12 +15,12 @@ "clean": "rm -rf ./dest .tsbuildinfo", "formatting": "run -T prettier --check ./src \"!src/web/main.js\" && run -T eslint ./src", "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src", - "test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", - "test:profile": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 0x --output-dir \"flame_graph/{pid}.0x\" -- node --experimental-vm-modules ../node_modules/jest/bin/jest.js --runInBand --testTimeout=300000 --forceExit", + "test": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test:profile": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 0x --output-dir \"flame_graph/{pid}.0x\" -- node --experimental-vm-modules ../node_modules/jest/bin/jest.js --runInBand --testTimeout=300000 --forceExit", "serve:flames": "python3 -m http.server --directory \"flame_graph\" 8000", - "test:debug": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --inspect --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", - "test:integration": "concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", - "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --no-cache --runInBand --config jest.integration.config.json", + "test:debug": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --inspect --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test:integration": "TIME_TRAVELER=${TIME_TRAVELER:-true} concurrently -k -s first -c reset,dim -n test,anvil \"yarn test:integration:run\" \"anvil\"", + "test:integration:run": "TIME_TRAVELER=${TIME_TRAVELER:-true} NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --no-cache --runInBand --config jest.integration.config.json", "test:unit": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest src/fixtures" }, "dependencies": { diff --git a/yarn-project/end-to-end/package.local.json b/yarn-project/end-to-end/package.local.json index 62f136fa45da..c76111c3c265 100644 --- a/yarn-project/end-to-end/package.local.json +++ b/yarn-project/end-to-end/package.local.json @@ -2,7 +2,7 @@ "scripts": { "build": "yarn clean && tsc -b && webpack", "formatting": "run -T prettier --check ./src \"!src/web/main.js\" && run -T eslint ./src", - "test": "LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", + "test": "TIME_TRAVELER=${TIME_TRAVELER:-true} LOG_LEVEL=${LOG_LEVEL:-verbose} DEBUG_COLORS=1 NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --testTimeout=300000 --forceExit", "test:unit": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest src/fixtures" } } \ No newline at end of file diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index c43e5ef32b63..fd8cb4eb86fe 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 @@ -77,6 +77,9 @@ const config = getConfigEnvVars(); const numberOfConsecutiveBlocks = 2; +// The initial archive is what we have in the genesis block in `Rollup.sol`. +const INITIAL_ARCHIVE = Fr.fromString('0x1200a06aae1368abe36530b585bd7a4d2ba4de5037b82076412691a187d7621e').toBuffer(); + describe('L1Publisher integration', () => { let publicClient: PublicClient; let walletClient: WalletClient; @@ -113,10 +116,10 @@ describe('L1Publisher integration', () => { // 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 progressTimeBySlot = async (slotsToJump = 1n) => { const currentTime = (await publicClient.getBlock()).timestamp; const currentSlot = await rollup.read.getCurrentSlot(); - const timestamp = (await rollup.read.getTimestampForSlot([currentSlot + 1n])) - BigInt(ETHEREUM_SLOT_DURATION); + const timestamp = await rollup.read.getTimestampForSlot([currentSlot + slotsToJump]); if (timestamp > currentTime) { await ethCheatCodes.warp(Number(timestamp)); } @@ -169,6 +172,7 @@ describe('L1Publisher integration', () => { publisherPrivateKey: sequencerPK, l1PublishRetryIntervalMS: 100, l1ChainId: 31337, + timeTraveler: true, }, new NoopTelemetryClient(), ); @@ -178,7 +182,9 @@ describe('L1Publisher integration', () => { prevHeader = builderDb.getInitialHeader(); - await setTimeToNextSlot(); + // We jump to the next epoch such that the committee can be setup. + const timeToJump = await rollup.read.EPOCH_DURATION(); + await progressTimeBySlot(timeToJump); }); const makeEmptyProcessedTx = () => @@ -345,7 +351,7 @@ describe('L1Publisher integration', () => { it(`Build ${numberOfConsecutiveBlocks} blocks of 4 bloated txs building on each other`, async () => { const archiveInRollup_ = await rollup.read.archive(); - expect(hexStringToBuffer(archiveInRollup_.toString())).toEqual(Buffer.alloc(32, 0)); + expect(hexStringToBuffer(archiveInRollup_.toString())).toEqual(INITIAL_ARCHIVE); const blockNumber = await publicClient.getBlockNumber(); // random recipient address, just kept consistent for easy testing ts/sol. @@ -463,13 +469,13 @@ describe('L1Publisher integration', () => { nextL1ToL2Messages = []; // @todo @LHerskind need to make sure that time have progressed to the next slot! - await setTimeToNextSlot(); + await progressTimeBySlot(); } }); it(`Build ${numberOfConsecutiveBlocks} blocks of 2 empty txs building on each other`, async () => { const archiveInRollup_ = await rollup.read.archive(); - expect(hexStringToBuffer(archiveInRollup_.toString())).toEqual(Buffer.alloc(32, 0)); + expect(hexStringToBuffer(archiveInRollup_.toString())).toEqual(INITIAL_ARCHIVE); const blockNumber = await publicClient.getBlockNumber(); @@ -542,7 +548,7 @@ describe('L1Publisher integration', () => { }); expect(ethTx.input).toEqual(expectedData); - await setTimeToNextSlot(); + await progressTimeBySlot(); } }); }); diff --git a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts index fed7d9ce6c19..c3ec8d93737b 100644 --- a/yarn-project/end-to-end/src/e2e_p2p_network.test.ts +++ b/yarn-project/end-to-end/src/e2e_p2p_network.test.ts @@ -16,6 +16,7 @@ import { RollupAbi } from '@aztec/l1-artifacts'; import { type BootstrapNode } from '@aztec/p2p'; import { type PXEService, createPXEService, getPXEServiceConfig as getRpcConfig } from '@aztec/pxe'; +import { jest } from '@jest/globals'; import fs from 'fs'; import { getContract } from 'viem'; import { mnemonicToAccount, privateKeyToAccount } from 'viem/accounts'; @@ -47,7 +48,13 @@ describe('e2e_p2p_network', () => { let deployL1ContractsValues: DeployL1Contracts; beforeEach(async () => { - ({ teardown, config, logger, deployL1ContractsValues } = await setup(0)); + // If we want to test with interval mining, we can use the local host and start `anvil --block-time 12` + const useLocalHost = false; + if (useLocalHost) { + jest.setTimeout(300_000); + } + const options = useLocalHost ? { l1RpcUrl: 'http://127.0.0.1:8545' } : {}; + ({ teardown, config, logger, deployL1ContractsValues } = await setup(0, options)); // It would likely be useful if we had the sequencers in such that they don't spam each other. // However, even if they do, it should still work. Not sure what caused the failure // Would be easier if I could see the errors from anvil as well, but those seem to be hidden. @@ -63,7 +70,7 @@ describe('e2e_p2p_network', () => { const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: 1 }); const publisherPrivKey = Buffer.from(hdAccount.getHdKey().privateKey!); const account = privateKeyToAccount(`0x${publisherPrivKey!.toString('hex')}`); - await rollup.write.addValidator([account.address]); + await rollup.write.addValidator([account.address], { gas: 1_000_000n }); logger.info(`Adding sequencer ${account.address}`); } else { // Add all nodes as validators - they will all sign attestations of each other's proposals @@ -71,17 +78,19 @@ describe('e2e_p2p_network', () => { const hdAccount = mnemonicToAccount(MNEMONIC, { addressIndex: i + 1 }); const publisherPrivKey = Buffer.from(hdAccount.getHdKey().privateKey!); const account = privateKeyToAccount(`0x${publisherPrivKey!.toString('hex')}`); - await rollup.write.addValidator([account.address]); + await rollup.write.addValidator([account.address], { gas: 1_000_000n }); logger.info(`Adding sequencer ${account.address}`); } } - // Now we jump ahead to the next epoch, such that the next epoch begins - const timeToJump = (await rollup.read.EPOCH_DURATION()) * (await rollup.read.SLOT_DURATION()); + //@note Now we jump ahead to the next epoch such that the validator committee is picked + // INTERVAL MINING: If we are using anvil interval mining this will NOT progress the time! + // Which means that the validator set will still be empty! So anyone can propose. + const slotsInEpoch = await rollup.read.EPOCH_DURATION(); + const timestamp = await rollup.read.getTimestampForSlot([slotsInEpoch]); const cheatCodes = new EthCheatCodes(config.l1RpcUrl); - const timestamp = (await cheatCodes.timestamp()) + Number(timeToJump); - await cheatCodes.warp(timestamp); + await cheatCodes.warp(Number(timestamp)); bootstrapNode = await createBootstrapNode(BOOT_NODE_UDP_PORT); bootstrapNodeEnr = bootstrapNode.getENR().encodeTxt(); @@ -175,7 +184,7 @@ describe('e2e_p2p_network', () => { i + 1 + BOOT_NODE_UDP_PORT, undefined, i, - /*validators*/ false, + /*validators*/ !IS_DEV_NET, `./data-${i}`, ); logger.info(`Node ${i} restarted`); diff --git a/yarn-project/ethereum/src/deploy_l1_contracts.ts b/yarn-project/ethereum/src/deploy_l1_contracts.ts index 8897a4d18116..a180e1fc48f6 100644 --- a/yarn-project/ethereum/src/deploy_l1_contracts.ts +++ b/yarn-project/ethereum/src/deploy_l1_contracts.ts @@ -152,7 +152,7 @@ export const deployL1Contracts = async ( // 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 rpcCall = async (method: string, params: any[]) => { const paramsString = JSON.stringify(params); const content = { body: `{"jsonrpc":"2.0", "method": "${method}", "params": ${paramsString}, "id": 1}`, @@ -161,8 +161,9 @@ export const deployL1Contracts = async ( }; return await (await fetch(rpcUrl, content)).json(); }; + // @todo #8084 const interval = 12; - const res = await rpcCall(rpcUrl, 'anvil_setBlockTimestampInterval', [interval]); + const res = await rpcCall('anvil_setBlockTimestampInterval', [interval]); if (res.error) { throw new Error(`Error setting block interval: ${res.error.message}`); } @@ -203,6 +204,7 @@ export const deployL1Contracts = async ( // @note This value MUST match what is in `constants.nr`. It is currently specified here instead of just importing // because there is circular dependency hell. This is a temporary solution. #3342 + // @todo #8084 const FEE_JUICE_INITIAL_MINT = 20000000000; const receipt = await feeJuice.write.mint([feeJuicePortalAddress.toString(), FEE_JUICE_INITIAL_MINT], {} as any); await publicClient.waitForTransactionReceipt({ hash: receipt }); @@ -234,13 +236,34 @@ export const deployL1Contracts = async ( ]); logger.info(`Deployed Rollup at ${rollupAddress}`); + const rollup = getContract({ + address: getAddress(rollupAddress.toString()), + abi: contractsToDeploy.rollup.contractAbi, + client: walletClient, + }); + + // @note We make a time jump PAST the very first slot to not have to deal with the edge case of the first slot + try { + // Need to get the time + const currentSlot = (await rollup.read.getCurrentSlot([])) as bigint; + + if (BigInt(currentSlot) === 0n) { + const ts = Number(await rollup.read.getTimestampForSlot([1])); + await rpcCall('evm_setNextBlockTimestamp', [ts]); + await rpcCall('hardhat_mine', [1]); + const currentSlot = (await rollup.read.getCurrentSlot([])) as bigint; + + if (BigInt(currentSlot) !== 1n) { + throw new Error(`Error jumping time: current slot is ${currentSlot}`); + } + logger.info(`Jumped to slot 1`); + } + } catch (e) { + throw new Error(`Error jumping time: ${e}`); + } + // Set initial blocks as proven if requested if (args.assumeProvenUntil && args.assumeProvenUntil > 0) { - const rollup = getContract({ - address: getAddress(rollupAddress.toString()), - abi: contractsToDeploy.rollup.contractAbi, - client: walletClient, - }); await rollup.write.setAssumeProvenUntilBlockNumber([BigInt(args.assumeProvenUntil)], { account }); logger.info(`Set Rollup assumedProvenUntil to ${args.assumeProvenUntil}`); } diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 10c3c4a22f8f..65035a3611be 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -60,6 +60,7 @@ export type EnvVar = | 'SEQ_PUBLISHER_PRIVATE_KEY' | 'SEQ_REQUIRED_CONFIRMATIONS' | 'SEQ_PUBLISH_RETRY_INTERVAL_MS' + | 'TIME_TRAVELER' | 'VERSION' | 'SEQ_DISABLED' | 'PROVER_DISABLED' diff --git a/yarn-project/sequencer-client/package.json b/yarn-project/sequencer-client/package.json index a6d7d7f0fec1..835dd9bbea1e 100644 --- a/yarn-project/sequencer-client/package.json +++ b/yarn-project/sequencer-client/package.json @@ -24,6 +24,7 @@ "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json" }, "dependencies": { + "@aztec/aztec.js": "workspace:^", "@aztec/bb-prover": "workspace:^", "@aztec/circuit-types": "workspace:^", "@aztec/circuits.js": "workspace:^", 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 f37db0af1cd8..91da4e1b46cf 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 @@ -52,23 +52,26 @@ export class GlobalVariableBuilder { * @param blockNumber - The block number to build global variables for. * @param coinbase - The address to receive block reward. * @param feeRecipient - The address to receive fees. + * @param slotNumber - The slot number to use for the global variables, if undefined it will be calculated. * @returns The global variables for the given block number. */ public async buildGlobalVariables( blockNumber: Fr, coinbase: EthAddress, feeRecipient: AztecAddress, + slotNumber?: bigint, ): Promise { const version = new Fr(await this.rollupContract.read.VERSION()); const chainId = new Fr(this.publicClient.chain.id); - const ts = (await this.publicClient.getBlock()).timestamp; + if (slotNumber === undefined) { + const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); + slotNumber = await this.rollupContract.read.getSlotAt([ts]); + } - // Not just the current slot, the slot of the next block. - const slot = await this.rollupContract.read.getSlotAt([ts + BigInt(ETHEREUM_SLOT_DURATION)]); - const timestamp = await this.rollupContract.read.getTimestampForSlot([slot]); + const timestamp = await this.rollupContract.read.getTimestampForSlot([slotNumber]); - const slotFr = new Fr(slot); + const slotFr = new Fr(slotNumber); const timestampFr = new Fr(timestamp); const gasFees = GasFees.default(); diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index bfe5eb42943c..65faaf37dc4e 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -1,5 +1,5 @@ import { type L1ReaderConfig, NULL_KEY } from '@aztec/ethereum'; -import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config'; +import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config'; /** * The configuration of the rollup transaction publisher. @@ -24,6 +24,10 @@ export interface PublisherConfig { * The interval to wait between publish retries. */ l1PublishRetryIntervalMS: number; + /** + * Whether the publisher is a time traveler and can warp the underlying chain + */ + timeTraveler: boolean; } export const getTxSenderConfigMappings: ( @@ -64,6 +68,11 @@ export const getPublisherConfigMappings: (scope: 'PROVER' | 'SEQ') => ConfigMapp defaultValue: 1000, description: 'The interval to wait between publish retries.', }, + timeTraveler: { + env: `TIME_TRAVELER`, + description: 'Whether the publisher is a time traveler and can warp the underlying chain', + ...booleanConfigHelper(), + }, }); export function getPublisherConfigFromEnv(scope: 'PROVER' | 'SEQ'): PublisherConfig { diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index 41b25de86a7f..e79a778393e7 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -1,5 +1,5 @@ import { L2Block } from '@aztec/circuit-types'; -import { EthAddress, Fr } from '@aztec/circuits.js'; +import { EthAddress } from '@aztec/circuits.js'; import { sleep } from '@aztec/foundation/sleep'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -18,7 +18,11 @@ interface MockAvailabilityOracleRead { } class MockAvailabilityOracle { - constructor(public write: MockAvailabilityOracleWrite, public read: MockAvailabilityOracleRead) {} + constructor( + public write: MockAvailabilityOracleWrite, + public simulate: MockAvailabilityOracleWrite, + public read: MockAvailabilityOracleRead, + ) {} } interface MockPublicClient { @@ -41,19 +45,26 @@ interface MockRollupContractWrite { interface MockRollupContractRead { archive: () => Promise<`0x${string}`>; + getCurrentSlot(): Promise; } class MockRollupContract { - constructor(public write: MockRollupContractWrite, public read: MockRollupContractRead) {} + constructor( + public write: MockRollupContractWrite, + public simulate: MockRollupContractWrite, + public read: MockRollupContractRead, + ) {} } describe('L1Publisher', () => { let rollupContractRead: MockProxy; let rollupContractWrite: MockProxy; + let rollupContractSimulate: MockProxy; let rollupContract: MockRollupContract; let availabilityOracleRead: MockProxy; let availabilityOracleWrite: MockProxy; + let availabilityOracleSimulate: MockProxy; let availabilityOracle: MockAvailabilityOracle; let publicClient: MockProxy; @@ -94,12 +105,18 @@ describe('L1Publisher', () => { } as unknown as GetTransactionReceiptReturnType; rollupContractWrite = mock(); + rollupContractSimulate = mock(); rollupContractRead = mock(); - rollupContract = new MockRollupContract(rollupContractWrite, rollupContractRead); + rollupContract = new MockRollupContract(rollupContractWrite, rollupContractSimulate, rollupContractRead); availabilityOracleWrite = mock(); availabilityOracleRead = mock(); - availabilityOracle = new MockAvailabilityOracle(availabilityOracleWrite, availabilityOracleRead); + availabilityOracleSimulate = mock(); + availabilityOracle = new MockAvailabilityOracle( + availabilityOracleWrite, + availabilityOracleSimulate, + availabilityOracleRead, + ); publicClient = mock(); @@ -112,6 +129,7 @@ describe('L1Publisher', () => { rollupAddress: EthAddress.ZERO.toString(), }, l1PublishRetryIntervalMS: 1, + timeTraveller: false, } as unknown as TxSenderConfig & PublisherConfig; publisher = new L1Publisher(config, new NoopTelemetryClient()); @@ -121,11 +139,14 @@ describe('L1Publisher', () => { (publisher as any)['publicClient'] = publicClient; account = (publisher as any)['account']; + + rollupContractRead.getCurrentSlot.mockResolvedValue(l2Block.header.globalVariables.slotNumber.toBigInt()); }); it('publishes and process l2 block to l1', async () => { rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); rollupContractWrite.publishAndProcess.mockResolvedValueOnce(publishAndProcessTxHash); + rollupContractSimulate.publishAndProcess.mockResolvedValueOnce(publishAndProcessTxHash); publicClient.getTransactionReceipt.mockResolvedValueOnce(publishAndProcessTxReceipt); const result = await publisher.processL2Block(l2Block); @@ -133,6 +154,7 @@ describe('L1Publisher', () => { expect(result).toEqual(true); const args = [`0x${header.toString('hex')}`, `0x${archive.toString('hex')}`, `0x${body.toString('hex')}`] as const; + expect(rollupContractSimulate.publishAndProcess).toHaveBeenCalledWith(args, { account: account }); expect(rollupContractWrite.publishAndProcess).toHaveBeenCalledWith(args, { account: account }); expect(publicClient.getTransactionReceipt).toHaveBeenCalledWith({ hash: publishAndProcessTxHash }); }); @@ -141,26 +163,18 @@ describe('L1Publisher', () => { availabilityOracleRead.isAvailable.mockResolvedValueOnce(true); rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); rollupContractWrite.process.mockResolvedValueOnce(processTxHash); + rollupContractSimulate.process.mockResolvedValueOnce(processTxHash); publicClient.getTransactionReceipt.mockResolvedValueOnce(processTxReceipt); const result = await publisher.processL2Block(l2Block); expect(result).toEqual(true); const args = [`0x${header.toString('hex')}`, `0x${archive.toString('hex')}`] as const; + expect(rollupContractSimulate.process).toHaveBeenCalledWith(args, { account }); expect(rollupContractWrite.process).toHaveBeenCalledWith(args, { account }); expect(publicClient.getTransactionReceipt).toHaveBeenCalledWith({ hash: processTxHash }); }); - it('does not publish if last archive root is different to expected', async () => { - rollupContractRead.archive.mockResolvedValue(Fr.random().toString()); - - const result = await publisher.processL2Block(l2Block); - expect(result).toBe(false); - expect(availabilityOracleWrite.publish).not.toHaveBeenCalled(); - expect(rollupContractWrite.process).not.toHaveBeenCalled(); - expect(rollupContractWrite.publishAndProcess).not.toHaveBeenCalled(); - }); - it('does not retry if sending a process tx fails', async () => { availabilityOracleRead.isAvailable.mockResolvedValueOnce(true); rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); @@ -168,14 +182,31 @@ describe('L1Publisher', () => { .mockRejectedValueOnce(new Error()) .mockResolvedValueOnce(processTxHash as `0x${string}`); + // Note that simulate will be valid both times + rollupContractSimulate.process + .mockResolvedValueOnce(processTxHash as `0x${string}`) + .mockResolvedValueOnce(processTxHash as `0x${string}`); + const result = await publisher.processL2Block(l2Block); expect(result).toEqual(false); expect(rollupContractWrite.process).toHaveBeenCalledTimes(1); }); + it('does not retry if simulating a publish and process tx fails', async () => { + rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); + rollupContractSimulate.publishAndProcess.mockRejectedValueOnce(new Error()); + + const result = await publisher.processL2Block(l2Block); + + expect(result).toEqual(false); + expect(rollupContractSimulate.publishAndProcess).toHaveBeenCalledTimes(1); + expect(rollupContractWrite.publishAndProcess).toHaveBeenCalledTimes(0); + }); + it('does not retry if sending a publish and process tx fails', async () => { rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); + rollupContractSimulate.publishAndProcess.mockResolvedValueOnce(publishAndProcessTxHash as `0x${string}`); rollupContractWrite.publishAndProcess.mockRejectedValueOnce(new Error()); const result = await publisher.processL2Block(l2Block); @@ -187,6 +218,7 @@ describe('L1Publisher', () => { it('retries if fetching the receipt fails (process)', async () => { availabilityOracleRead.isAvailable.mockResolvedValueOnce(true); rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); + rollupContractSimulate.process.mockResolvedValueOnce(processTxHash); rollupContractWrite.process.mockResolvedValueOnce(processTxHash); publicClient.getTransactionReceipt.mockRejectedValueOnce(new Error()).mockResolvedValueOnce(processTxReceipt); @@ -198,6 +230,7 @@ describe('L1Publisher', () => { it('retries if fetching the receipt fails (publish process)', async () => { rollupContractRead.archive.mockResolvedValue(l2Block.header.lastArchive.root.toString() as `0x${string}`); + rollupContractSimulate.publishAndProcess.mockResolvedValueOnce(publishAndProcessTxHash as `0x${string}`); rollupContractWrite.publishAndProcess.mockResolvedValueOnce(publishAndProcessTxHash as `0x${string}`); publicClient.getTransactionReceipt .mockRejectedValueOnce(new Error()) diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 405e68ea7368..620f674cbcf7 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -1,6 +1,14 @@ +import { EthCheatCodes } from '@aztec/aztec.js'; import { type L2Block, type Signature } from '@aztec/circuit-types'; import { type L1PublishBlockStats, type L1PublishProofStats } from '@aztec/circuit-types/stats'; -import { ETHEREUM_SLOT_DURATION, EthAddress, type Header, type Proof } from '@aztec/circuits.js'; +import { + AZTEC_SLOT_DURATION, + ETHEREUM_SLOT_DURATION, + EthAddress, + type Header, + IS_DEV_NET, + type Proof, +} from '@aztec/circuits.js'; import { createEthereumChain } from '@aztec/ethereum'; import { type Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; @@ -59,13 +67,6 @@ export type MinimalTransactionReceipt = { logs: any[]; }; -/** - * @notice An attestation for the sequencing model. - * @todo This is not where it belongs. But I think we should do a bigger rewrite of some of - * this spaghetti. - */ -export type Attestation = { isEmpty: boolean; v: number; r: `0x${string}`; s: `0x${string}` }; - /** Arguments to the process method of the rollup contract */ export type L1ProcessArgs = { /** The L2 block header. */ @@ -103,6 +104,7 @@ export type L1SubmitProofArgs = { export class L1Publisher { private interruptibleSleep = new InterruptibleSleep(); private sleepTimeMs: number; + private timeTraveler: boolean; private interrupted = false; private metrics: L1PublisherMetrics; private log = createDebugLogger('aztec:sequencer:publisher'); @@ -118,8 +120,11 @@ export class L1Publisher { private publicClient: PublicClient; private account: PrivateKeyAccount; + private ethCheatCodes: EthCheatCodes; + constructor(config: TxSenderConfig & PublisherConfig, client: TelemetryClient) { this.sleepTimeMs = config?.l1PublishRetryIntervalMS ?? 60_000; + this.timeTraveler = config?.timeTraveler ?? false; this.metrics = new L1PublisherMetrics(client, 'L1Publisher'); const { l1RpcUrl: rpcUrl, l1ChainId: chainId, publisherPrivateKey, l1Contracts } = config; @@ -146,30 +151,56 @@ export class L1Publisher { abi: RollupAbi, client: walletClient, }); + + this.ethCheatCodes = new EthCheatCodes(rpcUrl); + } + + public async amIAValidator(): Promise { + return await this.rollupContract.read.isValidator([this.account.address]); + } + + public async getValidatorCount(): Promise { + return BigInt(await this.rollupContract.read.getValidatorCount()); } public getSenderAddress(): Promise { return Promise.resolve(EthAddress.fromString(this.account.address)); } - // 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 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}`); - return EthAddress.ZERO; + public async willSimulationFail(slot: bigint): Promise { + // @note When simulating or estimating gas, `viem` will use the CURRENT state of the chain + // and not the state in the next block. Meaning that the timestamp will be the same as + // the previous block, which means that the slot will also be the same. + // This effectively means that if we try to simulate for the first L1 block where we + // will be proposer, we will have a failure as the slot have not yet changed. + // @todo #8110 + + if (IS_DEV_NET) { + return false; } + + const currentSlot = BigInt(await this.rollupContract.read.getCurrentSlot()); + return currentSlot != slot; } - public async isItMyTurnToSubmit(): Promise { - const submitter = await this.getProposerAtNextEthBlock(); - const sender = await this.getSenderAddress(); - return submitter.isZero() || submitter.equals(sender); + // @note Assumes that all ethereum slots have blocks + // Using next Ethereum block so we do NOT need to wait for it being mined before seeing the effect + public async getMetadataForSlotAtNextEthBlock(): Promise<[EthAddress, bigint, bigint, Buffer]> { + const ts = BigInt((await this.publicClient.getBlock()).timestamp + BigInt(ETHEREUM_SLOT_DURATION)); + + const [submitter, slot, pendingBlockCount, archive] = await Promise.all([ + this.rollupContract.read.getProposerAt([ts]), + this.rollupContract.read.getSlotAt([ts]), + this.rollupContract.read.pendingBlockCount(), + this.rollupContract.read.archive(), + ]); + + return [ + EthAddress.fromString(submitter), + slot, + pendingBlockCount - 1n, + Buffer.from(archive.replace('0x', ''), 'hex'), + ]; } public async getCurrentEpochCommittee(): Promise { @@ -201,24 +232,27 @@ export class L1Publisher { * @returns True once the tx has been confirmed and is successful, false on revert or interrupt, blocks otherwise. */ public async processL2Block(block: L2Block, attestations?: Signature[]): Promise { - const ctx = { blockNumber: block.number, blockHash: block.hash().toString() }; - // TODO(#4148) Remove this block number check, it's here because we don't currently have proper genesis state on the contract - const lastArchive = block.header.lastArchive.root.toBuffer(); - if (block.number != 1 && !(await this.checkLastArchiveHash(lastArchive))) { - this.log.info(`Detected different last archive prior to publishing a block, aborting publish...`, ctx); + const ctx = { + blockNumber: block.number, + slotNumber: block.header.globalVariables.slotNumber.toBigInt(), + blockHash: block.hash().toString(), + }; + + if (await this.willSimulationFail(block.header.globalVariables.slotNumber.toBigInt())) { + // @note See comment in willSimulationFail for more information + this.log.info(`Simulation will fail for slot ${block.header.globalVariables.slotNumber.toBigInt()}`); return false; } - const encodedBody = block.body.toBuffer(); const processTxArgs = { header: block.header.toBuffer(), archive: block.archive.root.toBuffer(), - body: encodedBody, + body: block.body.toBuffer(), attestations, }; // Process block and publish the body if needed (if not already published) - while (!this.interrupted) { + if (!this.interrupted) { let txHash; const timer = new Timer(); @@ -231,13 +265,13 @@ export class L1Publisher { if (!txHash) { this.log.info(`Failed to publish block ${block.number} to L1`, ctx); - break; + return false; } const receipt = await this.getTransactionReceipt(txHash); if (!receipt) { this.log.info(`Failed to get receipt for tx ${txHash}`, ctx); - break; + return false; } // Tx was mined successfully @@ -251,17 +285,14 @@ export class L1Publisher { }; this.log.info(`Published L2 block to L1 rollup contract`, { ...stats, ...ctx }); this.metrics.recordProcessBlockTx(timer.ms(), stats); + + await this.commitTimeJump(block.header.globalVariables.slotNumber.toBigInt() + 1n); + return true; } this.metrics.recordFailedTx('process'); - // Check if someone else incremented the block number - if (!(await this.checkLastArchiveHash(lastArchive))) { - this.log.warn('Publish failed. Detected different last archive hash.', ctx); - break; - } - this.log.error(`Rollup.process tx status failed: ${receipt.transactionHash}`, ctx); await this.sleepOrInterrupted(); } @@ -270,6 +301,47 @@ export class L1Publisher { return false; } + async commitTimeJump(slot: bigint) { + // @note So, we are cheating a bit here. Since the tests are running anvil auto-mine + // no blocks are coming around unless we do something, and since we cannot push + // more blocks within the same slot (when `IS_DEV_NET = false`), we can just + // fast forward the anvil chain such that the next block will be the one we need. + // this means that we are forwarding to time of the next slot - 12 seconds such that + // the NEXT ethereum block will be within the new slot. + // If the slot duration of L2 is just 1 L1 slot, then this will not do anything, as + // the time to jump to is current time. + // + // Time jumps only allowed into the future. + // + // If this is run on top of a real chain, the time lords will catch you. + + if (!this.timeTraveler) { + return; + } + + // If the aztec slot duration is same length as the ethereum slot duration, we don't need to do anything + if ((ETHEREUM_SLOT_DURATION as number) === (AZTEC_SLOT_DURATION as number)) { + return; + } + + const [currentTime, timeStampForSlot] = await Promise.all([ + this.ethCheatCodes.timestamp(), + this.rollupContract.read.getTimestampForSlot([slot]), + ]); + + // @note We progress the time to the next slot AND mine the block. + // This means that the next effective block will be ETHEREUM_SLOT_DURATION after that. + // This will cause issues if slot duration is equal to one (1) L1 slot, and sequencer selection is run + // The reason is that simulations on ANVIL cannot be run with timestamp + x, so we need to "BE" there. + // @todo #8110 + const timestamp = timeStampForSlot; // - BigInt(ETHEREUM_SLOT_DURATION); + + if (timestamp > currentTime) { + this.log.info(`Committing time jump to slot ${slot}`); + await this.ethCheatCodes.warp(Number(timestamp)); + } + } + public async submitProof( header: Header, archiveRoot: Fr, @@ -277,7 +349,7 @@ export class L1Publisher { aggregationObject: Fr[], proof: Proof, ): Promise { - const ctx = { blockNumber: header.globalVariables.blockNumber }; + const ctx = { blockNumber: header.globalVariables.blockNumber, slotNumber: header.globalVariables.slotNumber }; const txArgs: L1SubmitProofArgs = { header: header.toBuffer(), @@ -288,16 +360,16 @@ export class L1Publisher { }; // Process block - while (!this.interrupted) { + if (!this.interrupted) { const timer = new Timer(); const txHash = await this.sendSubmitProofTx(txArgs); if (!txHash) { - break; + return false; } const receipt = await this.getTransactionReceipt(txHash); if (!receipt) { - break; + return false; } // Tx was mined successfully @@ -338,26 +410,6 @@ export class L1Publisher { this.interrupted = false; } - async getCurrentArchive(): Promise { - const archive = await this.rollupContract.read.archive(); - return Buffer.from(archive.replace('0x', ''), 'hex'); - } - - /** - * Verifies that the given value of last archive in a block header equals current archive of the rollup contract - * @param lastArchive - The last archive of the block we wish to publish. - * @returns Boolean indicating if the hashes are equal. - */ - private async checkLastArchiveHash(lastArchive: Buffer): Promise { - const fromChain = await this.getCurrentArchive(); - const areSame = lastArchive.equals(fromChain); - if (!areSame) { - this.log.debug(`Contract archive: ${fromChain.toString('hex')}`); - this.log.debug(`New block last archive: ${lastArchive.toString('hex')}`); - } - return areSame; - } - private async sendSubmitProofTx(submitProofArgs: L1SubmitProofArgs): Promise { try { const size = Object.values(submitProofArgs).reduce((acc, arg) => acc + arg.length, 0); @@ -372,6 +424,10 @@ export class L1Publisher { `0x${proof.toString('hex')}`, ] as const; + await this.rollupContract.simulate.submitProof(args, { + account: this.account, + }); + return await this.rollupContract.write.submitProof(args, { account: this.account, }); @@ -382,11 +438,15 @@ export class L1Publisher { } private async sendPublishTx(encodedBody: Buffer): Promise { - while (!this.interrupted) { + if (!this.interrupted) { try { this.log.info(`TxEffects size=${encodedBody.length} bytes`); const args = [`0x${encodedBody.toString('hex')}`] as const; + await this.availabilityOracleContract.simulate.publish(args, { + account: this.account, + }); + return await this.availabilityOracleContract.write.publish(args, { account: this.account, }); @@ -398,7 +458,7 @@ export class L1Publisher { } private async sendProcessTx(encodedData: L1ProcessArgs): Promise { - while (!this.interrupted) { + if (!this.interrupted) { try { if (encodedData.attestations) { const attestations = encodedData.attestations.map(attest => attest.toViemSignature()); @@ -408,12 +468,16 @@ export class L1Publisher { attestations, ] as const; + await this.rollupContract.simulate.process(args, { account: this.account }); + return await this.rollupContract.write.process(args, { account: this.account, }); } else { const args = [`0x${encodedData.header.toString('hex')}`, `0x${encodedData.archive.toString('hex')}`] as const; + await this.rollupContract.simulate.process(args, { account: this.account }); + return await this.rollupContract.write.process(args, { account: this.account, }); @@ -426,9 +490,8 @@ export class L1Publisher { } private async sendPublishAndProcessTx(encodedData: L1ProcessArgs): Promise { - while (!this.interrupted) { + if (!this.interrupted) { try { - // @note This is quite a sin, but I'm committing war crimes in this code already. if (encodedData.attestations) { const attestations = encodedData.attestations.map(attest => attest.toViemSignature()); const args = [ @@ -438,6 +501,11 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; + // Using simulate to get a meaningful error message + await this.rollupContract.simulate.publishAndProcess(args, { + account: this.account, + }); + return await this.rollupContract.write.publishAndProcess(args, { account: this.account, }); @@ -448,6 +516,10 @@ export class L1Publisher { `0x${encodedData.body.toString('hex')}`, ] as const; + await this.rollupContract.simulate.publishAndProcess(args, { + account: this.account, + }); + return await this.rollupContract.write.publishAndProcess(args, { account: this.account, }); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 9f4f79046fa2..e1f546814ee7 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -1,4 +1,6 @@ import { + BlockAttestation, + BlockProposal, type BlockSimulator, type L1ToL2MessageSource, L2Block, @@ -7,7 +9,9 @@ import { PROVING_STATUS, type ProvingSuccess, type ProvingTicket, + Signature, type Tx, + TxHash, type UnencryptedL2Log, UnencryptedTxL2Logs, makeProcessedTx, @@ -22,6 +26,7 @@ import { IS_DEV_NET, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, } from '@aztec/circuits.js'; +import { Buffer32 } from '@aztec/foundation/buffer'; import { times } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; import { type Writeable } from '@aztec/foundation/types'; @@ -63,22 +68,41 @@ describe('sequencer', () => { const feeRecipient = AztecAddress.random(); const gasFees = GasFees.empty(); - // We mock an attestation - const mockedAttestation = { - isEmpty: false, - v: 27, - r: Fr.random().toString(), - s: Fr.random().toString(), + const archive = Fr.random(); + + const mockedSig = new Signature(Buffer32.fromField(Fr.random()), Buffer32.fromField(Fr.random()), 27); + + const committee = [EthAddress.random()]; + const getSignatures = () => (IS_DEV_NET ? undefined : [mockedSig]); + const getAttestations = () => { + if (IS_DEV_NET) { + return undefined; + } + + const attestation = new BlockAttestation(block.header, archive, mockedSig); + (attestation as any).sender = committee[0]; + + return [attestation]; + }; + const createBlockProposal = () => { + return new BlockProposal(block.header, archive, [TxHash.random()], mockedSig); }; - const getAttestations = () => (IS_DEV_NET ? undefined : [mockedAttestation]); + let block: L2Block; beforeEach(() => { lastBlockNumber = 0; - publisher = mock(); + block = L2Block.random(lastBlockNumber + 1); - publisher.isItMyTurnToSubmit.mockResolvedValue(true); + publisher = mock(); + publisher.getCurrentEpochCommittee.mockResolvedValue(committee); + publisher.getMetadataForSlotAtNextEthBlock.mockResolvedValue([ + EthAddress.ZERO, + block.header.globalVariables.slotNumber.toBigInt(), + BigInt(lastBlockNumber), + block.header.lastArchive.toBuffer(), + ]); globalVariableBuilder = mock(); merkleTreeOps = mock(); @@ -124,6 +148,13 @@ describe('sequencer', () => { create: () => blockSimulator, }); + if (!IS_DEV_NET) { + validatorClient = mock({ + collectAttestations: mockFn().mockResolvedValue(getAttestations()), + createBlockProposal: mockFn().mockResolvedValue(createBlockProposal()), + }); + } + sequencer = new TestSubject( publisher, // TDOO(md): add the relevant methods to the validator client that will prevent it stalling when waiting for attestations @@ -143,7 +174,7 @@ describe('sequencer', () => { it('builds a block out of a single tx', async () => { const tx = mockTxForRollup(); tx.data.constants.txContext.chainId = chainId; - const block = L2Block.random(lastBlockNumber + 1); + const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -178,14 +209,13 @@ describe('sequencer', () => { Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledTimes(1); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getAttestations()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); it('builds a block when it is their turn', async () => { const tx = mockTxForRollup(); tx.data.constants.txContext.chainId = chainId; - const block = L2Block.random(lastBlockNumber + 1); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -212,20 +242,34 @@ describe('sequencer', () => { globalVariableBuilder.buildGlobalVariables.mockResolvedValueOnce(mockedGlobalVariables); // Not your turn! - publisher.isItMyTurnToSubmit.mockClear().mockResolvedValue(false); + const publisherAddress = EthAddress.random(); + publisher.getSenderAddress.mockResolvedValue(publisherAddress); + publisher.getMetadataForSlotAtNextEthBlock.mockResolvedValue([ + EthAddress.random(), + block.header.globalVariables.slotNumber.toBigInt(), + BigInt(lastBlockNumber), + block.header.lastArchive.toBuffer(), + ]); + await sequencer.initialSync(); await sequencer.work(); expect(blockSimulator.startNewBlock).not.toHaveBeenCalled(); // Now it is! - publisher.isItMyTurnToSubmit.mockClear().mockResolvedValue(true); + publisher.getMetadataForSlotAtNextEthBlock.mockResolvedValue([ + publisherAddress, + block.header.globalVariables.slotNumber.toBigInt(), + BigInt(lastBlockNumber), + block.header.lastArchive.toBuffer(), + ]); + await sequencer.work(); expect(blockSimulator.startNewBlock).toHaveBeenCalledWith( 2, mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getAttestations()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -235,7 +279,6 @@ describe('sequencer', () => { tx.data.constants.txContext.chainId = chainId; }); const doubleSpendTx = txs[1]; - const block = L2Block.random(lastBlockNumber + 1); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -277,7 +320,7 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getAttestations()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); expect(p2p.deleteTxs).toHaveBeenCalledWith([doubleSpendTx.getTxHash()]); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -288,7 +331,6 @@ describe('sequencer', () => { tx.data.constants.txContext.chainId = chainId; }); const invalidChainTx = txs[1]; - const block = L2Block.random(lastBlockNumber + 1); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -325,7 +367,7 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getAttestations()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); expect(p2p.deleteTxs).toHaveBeenCalledWith([invalidChainTx.getTxHash()]); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -335,7 +377,6 @@ describe('sequencer', () => { txs.forEach(tx => { tx.data.constants.txContext.chainId = chainId; }); - const block = L2Block.random(lastBlockNumber + 1); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; @@ -373,7 +414,7 @@ describe('sequencer', () => { mockedGlobalVariables, Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); - expect(publisher.processL2Block).toHaveBeenCalledWith(block, getAttestations()); + expect(publisher.processL2Block).toHaveBeenCalledWith(block, getSignatures()); expect(blockSimulator.cancelBlock).toHaveBeenCalledTimes(0); }); @@ -563,7 +604,6 @@ describe('sequencer', () => { it('aborts building a block if the chain moves underneath it', async () => { const tx = mockTxForRollup(); tx.data.constants.txContext.chainId = chainId; - const block = L2Block.random(lastBlockNumber + 1); const result: ProvingSuccess = { status: PROVING_STATUS.SUCCESS, }; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 1fe8fa5f52c1..929f30cd1694 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -28,6 +28,12 @@ import { type TxValidatorFactory } from '../tx_validator/tx_validator_factory.js import { type SequencerConfig } from './config.js'; import { SequencerMetrics } from './metrics.js'; +export type ShouldProposeArgs = { + pendingTxsCount?: number; + validTxsCount?: number; + processedTxsCount?: number; +}; + /** * Sequencer client * - Wins a period of time to become the sequencer (depending on finalized protocol). @@ -183,39 +189,25 @@ export class Sequencer { this.state = SequencerState.IDLE; } - const historicalHeader = (await this.l2BlockSource.getBlock(-1))?.header; + const chainTip = await this.l2BlockSource.getBlock(-1); + const historicalHeader = chainTip?.header; + const newBlockNumber = (historicalHeader === undefined ? await this.l2BlockSource.getBlockNumber() : Number(historicalHeader.globalVariables.blockNumber.toBigInt())) + 1; - // Do not go forward with new block if not my turn - if (!(await this.publisher.isItMyTurnToSubmit())) { - this.log.debug('Not my turn to submit block'); - return; - } + const chainTipArchive = chainTip?.archive.root.toBuffer(); - if (this.isFlushing) { - this.log.verbose(`Flushing all pending txs in new block`); + let slot: bigint; + try { + slot = await this.canProposeBlock(historicalHeader, undefined, chainTipArchive); + } catch (err) { + this.log.debug(`Cannot propose for block ${newBlockNumber}`); + return; } - // Compute time elapsed since the previous block - const lastBlockTime = historicalHeader?.globalVariables.timestamp.toNumber() || 0; - const currentTime = Math.floor(Date.now() / 1000); - const elapsedSinceLastBlock = currentTime - lastBlockTime; - this.log.debug( - `Last block mined at ${lastBlockTime} current time is ${currentTime} (elapsed ${elapsedSinceLastBlock})`, - ); - - // Do not go forward with new block if not enough time has passed since last block - if ( - !this.isFlushing && - this.minSecondsBetweenBlocks > 0 && - elapsedSinceLastBlock < this.minSecondsBetweenBlocks - ) { - this.log.debug( - `Not creating block because not enough time ${this.minSecondsBetweenBlocks} has passed since last block`, - ); + if (!this.shouldProposeBlock(historicalHeader, {})) { return; } @@ -224,18 +216,8 @@ export class Sequencer { // Get txs to build the new block. const pendingTxs = this.p2pClient.getTxs('pending'); - // If we haven't hit the maxSecondsBetweenBlocks, we need to have at least minTxsPerBLock txs. - if (!this.isFlushing && pendingTxs.length < this.minTxsPerBLock) { - if (this.skipMinTxsPerBlockCheck(elapsedSinceLastBlock)) { - this.log.debug( - `Creating block with only ${pendingTxs.length} txs as more than ${this.maxSecondsBetweenBlocks}s have passed since last block`, - ); - } else { - this.log.debug( - `Not creating block because not enough txs in the pool (got ${pendingTxs.length} min ${this.minTxsPerBLock})`, - ); - return; - } + if (!this.shouldProposeBlock(historicalHeader, { pendingTxsCount: pendingTxs.length })) { + return; } this.log.debug(`Retrieved ${pendingTxs.length} txs from P2P pool`); @@ -243,10 +225,9 @@ export class Sequencer { new Fr(newBlockNumber), this._coinbase, this._feeRecipient, + slot, ); - // @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, @@ -261,18 +242,11 @@ export class Sequencer { const validTxs = this.takeTxsWithinMaxSize(allValidTxs); // Bail if we don't have enough valid txs - if ( - !this.isFlushing && - !this.skipMinTxsPerBlockCheck(elapsedSinceLastBlock) && - validTxs.length < this.minTxsPerBLock - ) { - this.log.debug( - `Not creating block because not enough valid txs loaded from the pool (got ${validTxs.length} min ${this.minTxsPerBLock})`, - ); + if (!this.shouldProposeBlock(historicalHeader, { validTxsCount: validTxs.length })) { return; } - await this.buildBlockAndPublish(validTxs, newGlobalVariables, historicalHeader, elapsedSinceLastBlock); + await this.buildBlockAndPublish(validTxs, newGlobalVariables, historicalHeader, chainTipArchive); } catch (err) { if (BlockProofError.isBlockProofError(err)) { const txHashes = err.txHashes.filter(h => !h.isZero()); @@ -285,38 +259,206 @@ export class Sequencer { } /** Whether to skip the check of min txs per block if more than maxSecondsBetweenBlocks has passed since the previous block. */ - private skipMinTxsPerBlockCheck(elapsed: number): boolean { + private skipMinTxsPerBlockCheck(historicalHeader: Header | undefined): boolean { + const lastBlockTime = historicalHeader?.globalVariables.timestamp.toNumber() || 0; + const currentTime = Math.floor(Date.now() / 1000); + const elapsed = currentTime - lastBlockTime; + return this.maxSecondsBetweenBlocks > 0 && elapsed >= this.maxSecondsBetweenBlocks; } - @trackSpan('Sequencer.buildBlockAndPublish', (_validTxs, newGlobalVariables, _historicalHeader) => ({ - [Attributes.BLOCK_NUMBER]: newGlobalVariables.blockNumber.toNumber(), - })) + async canProposeBlock( + historicalHeader?: Header, + globalVariables?: GlobalVariables, + tipArchive?: Buffer, + ): Promise { + // @note In order to be able to propose a block, a few conditions must be met: + // - We must be caught up to the pending chain + // - The tip archive must match the one from the L1 + // - The block number should match the one from the L1 + // - If we have built a block, the block number must match the next pending block + // - There cannot already be a block for the slot + // - If we are NOT in devnet, then the active slot must match the slot number of the block + // - The proposer must either be free for all or specifically us. + // + // Note that the ordering of these checks are NOT optimised for performance, but to resemble the ordering + // that is used in the Rollup contract: + // - _validateHeaderForSubmissionBase + // - _validateHeaderForSubmissionSequencerSelection + // + // Also, we are logging debug messages for checks that fail to make it easier to debug, as we are usually + // catching the errors. + + const [submitter, slot, pendingBlockNumber, archive] = await this.publisher.getMetadataForSlotAtNextEthBlock(); + + if (await this.publisher.willSimulationFail(slot)) { + // @note See comment in willSimulationFail for more information + const msg = `Simulation will fail for slot ${slot}`; + this.log.debug(msg); + throw new Error(msg); + } + + // If our tip of the chain is different from the tip on L1, we should not propose a block + // @note This will change along with the data publication changes. + if (tipArchive && !archive.equals(tipArchive)) { + const msg = `Tip archive does not match the one from the L1`; + this.log.debug(msg); + throw new Error(msg); + } + + // Make sure I'm caught up to the pending chain + if ( + pendingBlockNumber > 0 && + (historicalHeader == undefined || historicalHeader.globalVariables.blockNumber.toBigInt() != pendingBlockNumber) + ) { + const msg = `Not caught up to pending block ${pendingBlockNumber}`; + this.log.debug(msg); + throw new Error(msg); + } + + // If I have constructed a block, make sure that the block number matches the next pending block number + if (globalVariables) { + if (globalVariables.blockNumber.toBigInt() !== pendingBlockNumber + 1n) { + const msg = `Block number mismatch. Expected ${ + pendingBlockNumber + 1n + } but got ${globalVariables.blockNumber.toBigInt()}`; + this.log.debug(msg); + throw new Error(msg); + } + + const currentBlockNumber = await this.l2BlockSource.getBlockNumber(); + if (currentBlockNumber + 1 !== globalVariables.blockNumber.toNumber()) { + this.metrics.recordCancelledBlock(); + const msg = 'New block was emitted while building block'; + this.log.debug(msg); + throw new Error(msg); + } + } + + // Do not go forward if there was already a block for the slot + if (historicalHeader && historicalHeader.globalVariables.slotNumber.toBigInt() === slot) { + const msg = `Block already exists for slot ${slot}`; + this.log.debug(msg); + throw new Error(msg); + } + + // Related to _validateHeaderForSubmissionSequencerSelection + + if (IS_DEV_NET) { + // If we are in devnet, make sure that we are a validator + if ((await this.publisher.getValidatorCount()) != 0n && !(await this.publisher.amIAValidator())) { + const msg = 'Not a validator in devnet'; + this.log.debug(msg); + throw new Error(msg); + } + } else { + // If I have a constructed a block, make sure that the slot matches the current slot number + if (globalVariables) { + if (slot !== globalVariables.slotNumber.toBigInt()) { + const msg = `Slot number mismatch. Expected ${slot} but got ${globalVariables.slotNumber.toBigInt()}`; + this.log.debug(msg); + throw new Error(msg); + } + } + + // Do not go forward with new block if not free for all or my turn + if (!submitter.isZero() && !submitter.equals(await this.publisher.getSenderAddress())) { + const msg = 'Not my turn to submit block'; + this.log.debug(msg); + throw new Error(msg); + } + } + + return slot; + } + + shouldProposeBlock(historicalHeader: Header | undefined, args: ShouldProposeArgs): boolean { + if (this.isFlushing) { + this.log.verbose(`Flushing all pending txs in new block`); + return true; + } + + if (IS_DEV_NET) { + // Compute time elapsed since the previous block + const lastBlockTime = historicalHeader?.globalVariables.timestamp.toNumber() || 0; + const currentTime = Math.floor(Date.now() / 1000); + const elapsedSinceLastBlock = currentTime - lastBlockTime; + this.log.debug( + `Last block mined at ${lastBlockTime} current time is ${currentTime} (elapsed ${elapsedSinceLastBlock})`, + ); + + // If we haven't hit the maxSecondsBetweenBlocks, we need to have at least minTxsPerBLock txs. + // Do not go forward with new block if not enough time has passed since last block + if (this.minSecondsBetweenBlocks > 0 && elapsedSinceLastBlock < this.minSecondsBetweenBlocks) { + this.log.debug( + `Not creating block because not enough time ${this.minSecondsBetweenBlocks} has passed since last block`, + ); + return false; + } + } + + const skipCheck = this.skipMinTxsPerBlockCheck(historicalHeader); + + // If we haven't hit the maxSecondsBetweenBlocks, we need to have at least minTxsPerBLock txs. + if (args.pendingTxsCount != undefined) { + if (args.pendingTxsCount < this.minTxsPerBLock) { + if (skipCheck) { + this.log.debug( + `Creating block with only ${args.pendingTxsCount} txs as more than ${this.maxSecondsBetweenBlocks}s have passed since last block`, + ); + } else { + this.log.debug( + `Not creating block because not enough txs in the pool (got ${args.pendingTxsCount} min ${this.minTxsPerBLock})`, + ); + return false; + } + } + } + + // Bail if we don't have enough valid txs + if (args.validTxsCount != undefined) { + // Bail if we don't have enough valid txs + if (!skipCheck && args.validTxsCount < this.minTxsPerBLock) { + this.log.debug( + `Not creating block because not enough valid txs loaded from the pool (got ${args.validTxsCount} min ${this.minTxsPerBLock})`, + ); + return false; + } + } + + // TODO: This check should be processedTxs.length < this.minTxsPerBLock, so we don't publish a block with + // less txs than the minimum. But that'd cause the entire block to be aborted and retried. Instead, we should + // go back to the p2p pool and load more txs until we hit our minTxsPerBLock target. Only if there are no txs + // we should bail. + if (args.processedTxsCount != undefined) { + if (args.processedTxsCount === 0 && !skipCheck && this.minTxsPerBLock > 0) { + this.log.verbose('No txs processed correctly to build block. Exiting'); + return false; + } + } + + return true; + } + + async assertCanStillProposeBlock(): Promise {} + + @trackSpan( + 'Sequencer.buildBlockAndPublish', + (_validTxs, newGlobalVariables, _historicalHeader, _chainTipArchive) => ({ + [Attributes.BLOCK_NUMBER]: newGlobalVariables.blockNumber.toNumber(), + }), + ) private async buildBlockAndPublish( validTxs: Tx[], newGlobalVariables: GlobalVariables, historicalHeader: Header | undefined, - elapsedSinceLastBlock: number, + chainTipArchive: Buffer | undefined, ): Promise { this.metrics.recordNewBlock(newGlobalVariables.blockNumber.toNumber(), validTxs.length); const workTimer = new Timer(); this.state = SequencerState.CREATING_BLOCK; this.log.info(`Building block ${newGlobalVariables.blockNumber.toNumber()} with ${validTxs.length} transactions`); - const assertBlockHeight = async () => { - const currentBlockNumber = await this.l2BlockSource.getBlockNumber(); - if (currentBlockNumber + 1 !== newGlobalVariables.blockNumber.toNumber()) { - this.metrics.recordCancelledBlock(); - throw new Error('New block was emitted while building block'); - } - - 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 this.log.debug('Requesting L1 to L2 messages from contract'); const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(newGlobalVariables.blockNumber.toBigInt()); @@ -343,27 +485,21 @@ export class Sequencer { await this.p2pClient.deleteTxs(Tx.getHashes(failedTxData)); } - // TODO: This check should be processedTxs.length < this.minTxsPerBLock, so we don't publish a block with - // less txs than the minimum. But that'd cause the entire block to be aborted and retried. Instead, we should - // go back to the p2p pool and load more txs until we hit our minTxsPerBLock target. Only if there are no txs - // we should bail. + await this.canProposeBlock(historicalHeader, newGlobalVariables, chainTipArchive); if ( - !this.isFlushing && - processedTxs.length === 0 && - !this.skipMinTxsPerBlockCheck(elapsedSinceLastBlock) && - this.minTxsPerBLock > 0 + !this.shouldProposeBlock(historicalHeader, { + validTxsCount: validTxs.length, + processedTxsCount: processedTxs.length, + }) ) { - this.log.verbose('No txs processed correctly to build block. Exiting'); blockBuilder.cancelBlock(); return; } - await assertBlockHeight(); - // All real transactions have been added, set the block as full and complete the proving. await blockBuilder.setBlockCompleted(); - // Here we are now waiting for the block to be proven. + // Here we are now waiting for the block to be proven (using simulated[fake] proofs). // TODO(@PhilWindle) We should probably periodically check for things like another // block being published before ours instead of just waiting on our block const result = await blockTicket.provingPromise; @@ -371,12 +507,10 @@ export class Sequencer { throw new Error(`Block proving failed, reason: ${result.reason}`); } - await assertBlockHeight(); - - // Block is ready, now finalise and publish! + // Block is ready, now finalise const { block } = await blockBuilder.finaliseBlock(); - await assertBlockHeight(); + await this.canProposeBlock(historicalHeader, newGlobalVariables, chainTipArchive); const workDuration = workTimer.ms(); this.log.verbose( @@ -395,10 +529,12 @@ export class Sequencer { if (this.isFlushing) { this.log.verbose(`Flushing completed`); } + this.isFlushing = false; + const attestations = await this.collectAttestations(block); + await this.canProposeBlock(historicalHeader, newGlobalVariables, chainTipArchive); try { - const attestations = await this.collectAttestations(block); await this.publishL2Block(block, attestations); this.metrics.recordPublishedBlock(workDuration); this.log.info( @@ -437,6 +573,11 @@ export class Sequencer { // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962): inefficient to have a round trip in here - this should be cached const committee = await this.publisher.getCurrentEpochCommittee(); + + if (committee.length === 0) { + return undefined; + } + const numberOfRequiredAttestations = Math.floor((committee.length * 2) / 3) + 1; // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7974): we do not have transaction[] lists in the block for now @@ -448,10 +589,7 @@ export class Sequencer { this.validatorClient.broadcastBlockProposal(proposal); this.state = SequencerState.WAITING_FOR_ATTESTATIONS; - const attestations = await this.validatorClient.collectAttestations( - proposal.header.globalVariables.slotNumber.toBigInt(), - numberOfRequiredAttestations, - ); + const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations); // note: the smart contract requires that the signatures are provided in the order of the committee return await orderAttestations(attestations, committee); diff --git a/yarn-project/sequencer-client/tsconfig.json b/yarn-project/sequencer-client/tsconfig.json index 54c62d4427fc..9a8615c0299b 100644 --- a/yarn-project/sequencer-client/tsconfig.json +++ b/yarn-project/sequencer-client/tsconfig.json @@ -6,6 +6,9 @@ "tsBuildInfoFile": ".tsbuildinfo" }, "references": [ + { + "path": "../aztec.js" + }, { "path": "../bb-prover" }, diff --git a/yarn-project/validator-client/src/validator.ts b/yarn-project/validator-client/src/validator.ts index a0338ddadb0f..1425f7d464c7 100644 --- a/yarn-project/validator-client/src/validator.ts +++ b/yarn-project/validator-client/src/validator.ts @@ -20,7 +20,7 @@ export interface Validator { // TODO(md): possible abstraction leak broadcastBlockProposal(proposal: BlockProposal): void; - collectAttestations(slot: bigint, numberOfRequiredAttestations: number): Promise; + collectAttestations(proposal: BlockProposal, numberOfRequiredAttestations: number): Promise; } /** Validator Client @@ -75,13 +75,18 @@ export class ValidatorClient implements Validator { // Target is temporarily hardcoded, for a test, but will be calculated from smart contract // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962) // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7976): require suitable timeouts - async collectAttestations(slot: bigint, numberOfRequiredAttestations: number): Promise { + async collectAttestations( + proposal: BlockProposal, + numberOfRequiredAttestations: number, + ): Promise { // Wait and poll the p2pClients attestation pool for this block // until we have enough attestations - this.log.info(`Waiting for attestations for slot, ${slot}`); + const slot = proposal.header.globalVariables.slotNumber.toBigInt(); - let attestations: BlockAttestation[] = []; + this.log.info(`Waiting for ${numberOfRequiredAttestations} attestations for slot: ${slot}`); + + let attestations: BlockAttestation[] = [await this.attestToProposal(proposal)]; while (attestations.length < numberOfRequiredAttestations) { attestations = await this.p2pClient.getAttestationsForSlot(slot); diff --git a/yarn-project/yarn.lock b/yarn-project/yarn.lock index 2f89126d3f8b..e325bdd7b594 100644 --- a/yarn-project/yarn.lock +++ b/yarn-project/yarn.lock @@ -1018,6 +1018,7 @@ __metadata: version: 0.0.0-use.local resolution: "@aztec/sequencer-client@workspace:sequencer-client" dependencies: + "@aztec/aztec.js": "workspace:^" "@aztec/bb-prover": "workspace:^" "@aztec/circuit-types": "workspace:^" "@aztec/circuits.js": "workspace:^"