diff --git a/l1-contracts/slither_output.md b/l1-contracts/slither_output.md index 3fb86f9058f..8ff58c77191 100644 --- a/l1-contracts/slither_output.md +++ b/l1-contracts/slither_output.md @@ -1,7 +1,7 @@ Summary - [pess-unprotected-setter](#pess-unprotected-setter) (1 results) (High) - [uninitialized-local](#uninitialized-local) (2 results) (Medium) - - [unused-return](#unused-return) (2 results) (Medium) + - [unused-return](#unused-return) (1 results) (Medium) - [pess-dubious-typecast](#pess-dubious-typecast) (8 results) (Medium) - [missing-zero-check](#missing-zero-check) (1 results) (Low) - [reentrancy-events](#reentrancy-events) (2 results) (Low) @@ -18,9 +18,9 @@ Summary Impact: High Confidence: Medium - [ ] ID-0 -Function [Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L103) is a non-protected setter archive is written +Function [Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L101) is a non-protected setter archive is written -src/core/Rollup.sol#L58-L103 +src/core/Rollup.sol#L58-L101 ## uninitialized-local @@ -42,35 +42,29 @@ src/core/libraries/decoders/TxsDecoder.sol#L79 Impact: Medium Confidence: Medium - [ ] ID-3 -[Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L103) ignores return value by [NEW_INBOX.consume()](src/core/Rollup.sol#L93) +[Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L101) ignores return value by [(l1ToL2Msgs,l2ToL1Msgs) = MessagesDecoder.decode(_body)](src/core/Rollup.sol#L74) -src/core/Rollup.sol#L58-L103 - - - - [ ] ID-4 -[Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L103) ignores return value by [(l1ToL2Msgs,l2ToL1Msgs) = MessagesDecoder.decode(_body)](src/core/Rollup.sol#L74) - -src/core/Rollup.sol#L58-L103 +src/core/Rollup.sol#L58-L101 ## pess-dubious-typecast Impact: Medium Confidence: High - - [ ] ID-5 + - [ ] ID-4 Dubious typecast in [TxsDecoder.read1(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L314-L316): bytes => bytes1 casting occurs in [uint256(uint8(bytes1(slice(_data,_offset,1))))](src/core/libraries/decoders/TxsDecoder.sol#L315) src/core/libraries/decoders/TxsDecoder.sol#L314-L316 - - [ ] ID-6 + - [ ] ID-5 Dubious typecast in [Outbox.sendL1Messages(bytes32[])](src/core/messagebridge/Outbox.sol#L38-L46): uint256 => uint32 casting occurs in [version = uint32(REGISTRY.getVersionFor(msg.sender))](src/core/messagebridge/Outbox.sol#L40) src/core/messagebridge/Outbox.sol#L38-L46 - - [ ] ID-7 + - [ ] ID-6 Dubious typecast in [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,bytes32)](src/core/messagebridge/Inbox.sol#L45-L91): uint256 => uint64 casting occurs in [fee = uint64(msg.value)](src/core/messagebridge/Inbox.sol#L64) uint256 => uint32 casting occurs in [entries.insert(key,fee,uint32(_recipient.version),_deadline,_errIncompatibleEntryArguments)](src/core/messagebridge/Inbox.sol#L76) @@ -78,28 +72,28 @@ Dubious typecast in [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,b src/core/messagebridge/Inbox.sol#L45-L91 - - [ ] ID-8 + - [ ] ID-7 Dubious typecast in [TxsDecoder.read4(bytes,uint256)](src/core/libraries/decoders/TxsDecoder.sol#L324-L326): bytes => bytes4 casting occurs in [uint256(uint32(bytes4(slice(_data,_offset,4))))](src/core/libraries/decoders/TxsDecoder.sol#L325) src/core/libraries/decoders/TxsDecoder.sol#L324-L326 - - [ ] ID-9 + - [ ] ID-8 Dubious typecast in [MessagesDecoder.read4(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L160-L162): bytes => bytes4 casting occurs in [uint256(uint32(bytes4(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L161) src/core/libraries/decoders/MessagesDecoder.sol#L160-L162 - - [ ] ID-10 + - [ ] ID-9 Dubious typecast in [Inbox.batchConsume(bytes32[],address)](src/core/messagebridge/Inbox.sol#L122-L143): uint256 => uint32 casting occurs in [expectedVersion = uint32(REGISTRY.getVersionFor(msg.sender))](src/core/messagebridge/Inbox.sol#L128) src/core/messagebridge/Inbox.sol#L122-L143 - - [ ] ID-11 + - [ ] ID-10 Dubious typecast in [HeaderLib.decode(bytes)](src/core/libraries/HeaderLib.sol#L143-L184): bytes => bytes32 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L151-L153) bytes => bytes4 casting occurs in [header.lastArchive = AppendOnlyTreeSnapshot(bytes32(_header),uint32(bytes4(_header)))](src/core/libraries/HeaderLib.sol#L151-L153) @@ -125,7 +119,7 @@ Dubious typecast in [HeaderLib.decode(bytes)](src/core/libraries/HeaderLib.sol#L src/core/libraries/HeaderLib.sol#L143-L184 - - [ ] ID-12 + - [ ] ID-11 Dubious typecast in [MessagesDecoder.read1(bytes,uint256)](src/core/libraries/decoders/MessagesDecoder.sol#L150-L152): bytes => bytes1 casting occurs in [uint256(uint8(bytes1(_data)))](src/core/libraries/decoders/MessagesDecoder.sol#L151) @@ -135,7 +129,7 @@ src/core/libraries/decoders/MessagesDecoder.sol#L150-L152 ## missing-zero-check Impact: Low Confidence: Medium - - [ ] ID-13 + - [ ] ID-12 [NewInbox.constructor(address,uint256)._rollup](src/core/messagebridge/NewInbox.sol#L41) lacks a zero-check on : - [ROLLUP = _rollup](src/core/messagebridge/NewInbox.sol#L42) @@ -145,7 +139,7 @@ src/core/messagebridge/NewInbox.sol#L41 ## reentrancy-events Impact: Low Confidence: Medium - - [ ] ID-14 + - [ ] ID-13 Reentrancy in [NewInbox.sendL2Message(DataStructures.L2Actor,bytes32,bytes32)](src/core/messagebridge/NewInbox.sol#L62-L99): External calls: - [index = currentTree.insertLeaf(leaf)](src/core/messagebridge/NewInbox.sol#L95) @@ -155,22 +149,22 @@ Reentrancy in [NewInbox.sendL2Message(DataStructures.L2Actor,bytes32,bytes32)](s src/core/messagebridge/NewInbox.sol#L62-L99 - - [ ] ID-15 -Reentrancy in [Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L103): + - [ ] ID-14 +Reentrancy in [Rollup.process(bytes,bytes32,bytes,bytes)](src/core/Rollup.sol#L58-L101): External calls: - [inbox.batchConsume(l1ToL2Msgs,msg.sender)](src/core/Rollup.sol#L90) - - [NEW_INBOX.consume()](src/core/Rollup.sol#L93) - - [outbox.sendL1Messages(l2ToL1Msgs)](src/core/Rollup.sol#L100) + - [inHash = NEW_INBOX.consume()](src/core/Rollup.sol#L92) + - [outbox.sendL1Messages(l2ToL1Msgs)](src/core/Rollup.sol#L98) Event emitted after the call(s): - - [L2BlockProcessed(header.globalVariables.blockNumber)](src/core/Rollup.sol#L102) + - [L2BlockProcessed(header.globalVariables.blockNumber)](src/core/Rollup.sol#L100) -src/core/Rollup.sol#L58-L103 +src/core/Rollup.sol#L58-L101 ## timestamp Impact: Low Confidence: Medium - - [ ] ID-16 + - [ ] ID-15 [Inbox.batchConsume(bytes32[],address)](src/core/messagebridge/Inbox.sol#L122-L143) uses timestamp for comparisons Dangerous comparisons: - [block.timestamp > entry.deadline](src/core/messagebridge/Inbox.sol#L136) @@ -178,7 +172,7 @@ Confidence: Medium src/core/messagebridge/Inbox.sol#L122-L143 - - [ ] ID-17 + - [ ] ID-16 [HeaderLib.validate(HeaderLib.Header,uint256,uint256,bytes32)](src/core/libraries/HeaderLib.sol#L106-L136) uses timestamp for comparisons Dangerous comparisons: - [_header.globalVariables.timestamp > block.timestamp](src/core/libraries/HeaderLib.sol#L120) @@ -186,7 +180,7 @@ src/core/messagebridge/Inbox.sol#L122-L143 src/core/libraries/HeaderLib.sol#L106-L136 - - [ ] ID-18 + - [ ] ID-17 [Inbox.sendL2Message(DataStructures.L2Actor,uint32,bytes32,bytes32)](src/core/messagebridge/Inbox.sol#L45-L91) uses timestamp for comparisons Dangerous comparisons: - [_deadline <= block.timestamp](src/core/messagebridge/Inbox.sol#L54) @@ -194,7 +188,7 @@ src/core/libraries/HeaderLib.sol#L106-L136 src/core/messagebridge/Inbox.sol#L45-L91 - - [ ] ID-19 + - [ ] ID-18 [Inbox.cancelL2Message(DataStructures.L1ToL2Msg,address)](src/core/messagebridge/Inbox.sol#L102-L113) uses timestamp for comparisons Dangerous comparisons: - [block.timestamp <= _message.deadline](src/core/messagebridge/Inbox.sol#L108) @@ -205,28 +199,28 @@ src/core/messagebridge/Inbox.sol#L102-L113 ## pess-public-vs-external Impact: Low Confidence: Medium - - [ ] ID-20 + - [ ] ID-19 The following public functions could be turned into external in [FrontierMerkle](src/core/messagebridge/frontier_tree/Frontier.sol#L7-L93) contract: [FrontierMerkle.constructor(uint256)](src/core/messagebridge/frontier_tree/Frontier.sol#L19-L27) src/core/messagebridge/frontier_tree/Frontier.sol#L7-L93 - - [ ] ID-21 + - [ ] ID-20 The following public functions could be turned into external in [Registry](src/core/messagebridge/Registry.sol#L22-L129) contract: [Registry.constructor()](src/core/messagebridge/Registry.sol#L29-L33) src/core/messagebridge/Registry.sol#L22-L129 - - [ ] ID-22 -The following public functions could be turned into external in [Rollup](src/core/Rollup.sol#L30-L112) contract: + - [ ] ID-21 +The following public functions could be turned into external in [Rollup](src/core/Rollup.sol#L30-L110) contract: [Rollup.constructor(IRegistry,IAvailabilityOracle)](src/core/Rollup.sol#L43-L49) -src/core/Rollup.sol#L30-L112 +src/core/Rollup.sol#L30-L110 - - [ ] ID-23 + - [ ] ID-22 The following public functions could be turned into external in [Outbox](src/core/messagebridge/Outbox.sol#L21-L148) contract: [Outbox.constructor(address)](src/core/messagebridge/Outbox.sol#L29-L31) [Outbox.get(bytes32)](src/core/messagebridge/Outbox.sol#L77-L84) @@ -235,7 +229,7 @@ The following public functions could be turned into external in [Outbox](src/cor src/core/messagebridge/Outbox.sol#L21-L148 - - [ ] ID-24 + - [ ] ID-23 The following public functions could be turned into external in [Inbox](src/core/messagebridge/Inbox.sol#L21-L231) contract: [Inbox.constructor(address)](src/core/messagebridge/Inbox.sol#L30-L32) [Inbox.contains(bytes32)](src/core/messagebridge/Inbox.sol#L174-L176) @@ -243,7 +237,7 @@ The following public functions could be turned into external in [Inbox](src/core src/core/messagebridge/Inbox.sol#L21-L231 - - [ ] ID-25 + - [ ] ID-24 The following public functions could be turned into external in [NewInbox](src/core/messagebridge/NewInbox.sol#L25-L128) contract: [NewInbox.constructor(address,uint256)](src/core/messagebridge/NewInbox.sol#L41-L52) @@ -253,7 +247,7 @@ src/core/messagebridge/NewInbox.sol#L25-L128 ## assembly Impact: Informational Confidence: High - - [ ] ID-26 + - [ ] ID-25 [MessagesDecoder.decode(bytes)](src/core/libraries/decoders/MessagesDecoder.sol#L60-L142) uses assembly - [INLINE ASM](src/core/libraries/decoders/MessagesDecoder.sol#L79-L81) - [INLINE ASM](src/core/libraries/decoders/MessagesDecoder.sol#L112-L118) @@ -261,7 +255,7 @@ Confidence: High src/core/libraries/decoders/MessagesDecoder.sol#L60-L142 - - [ ] ID-27 + - [ ] ID-26 [TxsDecoder.computeRoot(bytes32[])](src/core/libraries/decoders/TxsDecoder.sol#L256-L275) uses assembly - [INLINE ASM](src/core/libraries/decoders/TxsDecoder.sol#L263-L265) @@ -271,31 +265,31 @@ src/core/libraries/decoders/TxsDecoder.sol#L256-L275 ## dead-code Impact: Informational Confidence: Medium - - [ ] ID-28 + - [ ] ID-27 [Inbox._errIncompatibleEntryArguments(bytes32,uint64,uint64,uint32,uint32,uint32,uint32)](src/core/messagebridge/Inbox.sol#L212-L230) is never used and should be removed src/core/messagebridge/Inbox.sol#L212-L230 - - [ ] ID-29 + - [ ] ID-28 [Outbox._errNothingToConsume(bytes32)](src/core/messagebridge/Outbox.sol#L114-L116) is never used and should be removed src/core/messagebridge/Outbox.sol#L114-L116 - - [ ] ID-30 + - [ ] ID-29 [Hash.sha256ToField(bytes32)](src/core/libraries/Hash.sol#L59-L61) is never used and should be removed src/core/libraries/Hash.sol#L59-L61 - - [ ] ID-31 + - [ ] ID-30 [Inbox._errNothingToConsume(bytes32)](src/core/messagebridge/Inbox.sol#L197-L199) is never used and should be removed src/core/messagebridge/Inbox.sol#L197-L199 - - [ ] ID-32 + - [ ] ID-31 [Outbox._errIncompatibleEntryArguments(bytes32,uint64,uint64,uint32,uint32,uint32,uint32)](src/core/messagebridge/Outbox.sol#L129-L147) is never used and should be removed src/core/messagebridge/Outbox.sol#L129-L147 @@ -304,13 +298,13 @@ src/core/messagebridge/Outbox.sol#L129-L147 ## solc-version Impact: Informational Confidence: High - - [ ] ID-33 + - [ ] ID-32 solc-0.8.21 is not recommended for deployment ## low-level-calls Impact: Informational Confidence: High - - [ ] ID-34 + - [ ] ID-33 Low level call in [Inbox.withdrawFees()](src/core/messagebridge/Inbox.sol#L148-L153): - [(success) = msg.sender.call{value: balance}()](src/core/messagebridge/Inbox.sol#L151) @@ -320,19 +314,19 @@ src/core/messagebridge/Inbox.sol#L148-L153 ## similar-names Impact: Informational Confidence: Medium - - [ ] ID-35 + - [ ] ID-34 Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L132) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L125) src/core/libraries/ConstantsGen.sol#L132 - - [ ] ID-36 + - [ ] ID-35 Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L112) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L113) src/core/libraries/ConstantsGen.sol#L112 - - [ ] ID-37 + - [ ] ID-36 Variable [Rollup.AVAILABILITY_ORACLE](src/core/Rollup.sol#L33) is too similar to [Rollup.constructor(IRegistry,IAvailabilityOracle)._availabilityOracle](src/core/Rollup.sol#L43) src/core/Rollup.sol#L33 @@ -341,7 +335,7 @@ src/core/Rollup.sol#L33 ## constable-states Impact: Optimization Confidence: High - - [ ] ID-38 + - [ ] ID-37 [Rollup.lastWarpedBlockTs](src/core/Rollup.sol#L41) should be constant src/core/Rollup.sol#L41 @@ -350,31 +344,31 @@ src/core/Rollup.sol#L41 ## pess-multiple-storage-read Impact: Optimization Confidence: High - - [ ] ID-39 + - [ ] ID-38 In a function [NewInbox.sendL2Message(DataStructures.L2Actor,bytes32,bytes32)](src/core/messagebridge/NewInbox.sol#L62-L99) variable [NewInbox.inProgress](src/core/messagebridge/NewInbox.sol#L37) is read multiple times src/core/messagebridge/NewInbox.sol#L62-L99 - - [ ] ID-40 + - [ ] ID-39 In a function [FrontierMerkle.root()](src/core/messagebridge/frontier_tree/Frontier.sol#L43-L76) variable [FrontierMerkle.HEIGHT](src/core/messagebridge/frontier_tree/Frontier.sol#L8) is read multiple times src/core/messagebridge/frontier_tree/Frontier.sol#L43-L76 - - [ ] ID-41 + - [ ] ID-40 In a function [NewInbox.consume()](src/core/messagebridge/NewInbox.sol#L108-L127) variable [NewInbox.inProgress](src/core/messagebridge/NewInbox.sol#L37) is read multiple times src/core/messagebridge/NewInbox.sol#L108-L127 - - [ ] ID-42 + - [ ] ID-41 In a function [NewInbox.consume()](src/core/messagebridge/NewInbox.sol#L108-L127) variable [NewInbox.toConsume](src/core/messagebridge/NewInbox.sol#L35) is read multiple times src/core/messagebridge/NewInbox.sol#L108-L127 - - [ ] ID-43 + - [ ] ID-42 In a function [FrontierMerkle.root()](src/core/messagebridge/frontier_tree/Frontier.sol#L43-L76) variable [FrontierMerkle.frontier](src/core/messagebridge/frontier_tree/Frontier.sol#L13) is read multiple times src/core/messagebridge/frontier_tree/Frontier.sol#L43-L76 diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index a898c6ceab8..f82ca13559c 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -89,12 +89,10 @@ contract Rollup is IRollup { IInbox inbox = REGISTRY.getInbox(); inbox.batchConsume(l1ToL2Msgs, msg.sender); - // TODO(#4633): enable the inHash check - NEW_INBOX.consume(); - // bytes32 inHash = NEW_INBOX.consume(); - // if (header.contentCommitment.inHash != inHash) { - // revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); - // } + bytes32 inHash = NEW_INBOX.consume(); + if (header.contentCommitment.inHash != inHash) { + revert Errors.Rollup__InvalidInHash(inHash, header.contentCommitment.inHash); + } IOutbox outbox = REGISTRY.getOutbox(); outbox.sendL1Messages(l2ToL1Msgs); diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 09b5137d2cd..253bb31f9cd 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -130,4 +130,6 @@ library Constants { uint256 internal constant CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED = 52; uint256 internal constant L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = 64; uint256 internal constant LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; + uint256 internal constant NUM_MSGS_PER_BASE_PARITY = 4; + uint256 internal constant NUM_BASE_PARITY_PER_ROOT_PARITY = 4; } diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index 568bbda37c6..6cc41709fbd 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -49,6 +49,7 @@ library Errors { // Rollup error Rollup__InvalidArchive(bytes32 expected, bytes32 actual); // 0xb682a40e + error Rollup__InvalidInHash(bytes32 expected, bytes32 actual); // 0xcd6f4233 error Rollup__InvalidProof(); // 0xa5b2ba17 error Rollup__InvalidChainId(uint256 expected, uint256 actual); // 0x37b5bc12 error Rollup__InvalidVersion(uint256 expected, uint256 actual); // 0x9ef30794 diff --git a/l1-contracts/src/core/messagebridge/NewInbox.sol b/l1-contracts/src/core/messagebridge/NewInbox.sol index 1a0185cb30b..ddf618a5956 100644 --- a/l1-contracts/src/core/messagebridge/NewInbox.sol +++ b/l1-contracts/src/core/messagebridge/NewInbox.sol @@ -34,7 +34,7 @@ contract NewInbox is INewInbox { // Number of a tree which is ready to be consumed uint256 public toConsume = Constants.INITIAL_L2_BLOCK_NUM; // Number of a tree which is currently being filled - uint256 public inProgress = 2; + uint256 public inProgress = Constants.INITIAL_L2_BLOCK_NUM + 1; mapping(uint256 blockNumber => IFrontier tree) internal trees; diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 93f4433a5e6..b8ed7ceaa63 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -184,6 +184,11 @@ contract RollupTest is DecoderBase { inbox.sendL2Message( DataStructures.L2Actor({actor: _recipient, version: 1}), deadline, _contents[i], bytes32(0) ); + + vm.prank(_sender); + newInbox.sendL2Message( + DataStructures.L2Actor({actor: _recipient, version: 1}), _contents[i], bytes32(0) + ); } } } diff --git a/l1-contracts/test/fixtures/empty_block_0.json b/l1-contracts/test/fixtures/empty_block_0.json index 6d041901550..6d0b5c1e213 100644 --- a/l1-contracts/test/fixtures/empty_block_0.json +++ b/l1-contracts/test/fixtures/empty_block_0.json @@ -35,12 +35,12 @@ ] }, "block": { - "archive": "0x2c80dc48494603ac15fa1ea88e3cd79565bdd54cf067a9bb4da9849870b60c69", + "archive": "0x02c6f1a862fd5dbef12bdeccfcc2bcf18a5c5b26c0465ac6470bc2c84e162695", "body": "0x00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9", "decodedHeader": { "contentCommitment": { - "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "inHash": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", "outHash": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", "txTreeHeight": 2, "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9" @@ -78,8 +78,8 @@ } } }, - "header": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f0000000100000000000000000000000000000000000000000000000000000000000000029139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a90000000000000000000000000000000000000000000000000000000000000000c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000066440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba", + "header": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f0000000100000000000000000000000000000000000000000000000000000000000000029139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123cc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000066440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba", "l1ToL2MessagesHash": "0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560", - "publicInputsHash": "0x22fb6cb24475c172eea140a775dd4ca748f8dda94fda256d5f76c09cb913ecf0" + "publicInputsHash": "0x2a2aa21195442355cb37f9b6f1f7099d2e93c465fd01ad5df56c4aee474cd768" } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 71397610889..9f684f3ea7d 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -35,12 +35,12 @@ ] }, "block": { - "archive": "0x0dbc2a0e8143bb92a0f8a92c8a9862c4577f15b01330d89960032af0dadf5b52", + "archive": "0x2cff40994bd00149d898c0c92ad0c5713b04077e2f8d150f27febd4fbfeac114", "body": "0x00000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9", "decodedHeader": { "contentCommitment": { - "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "inHash": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", "outHash": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", "txTreeHeight": 2, "txsEffectsHash": "0x9139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9" @@ -48,14 +48,14 @@ "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1710254478, + "timestamp": 1710325403, "version": 1, "coinbase": "0x66440eb666440eb666440eb666440eb666440eb6", "feeRecipient": "0x061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba" }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x2c80dc48494603ac15fa1ea88e3cd79565bdd54cf067a9bb4da9849870b60c69" + "root": "0x02c6f1a862fd5dbef12bdeccfcc2bcf18a5c5b26c0465ac6470bc2c84e162695" }, "stateReference": { "l1ToL2MessageTree": { @@ -78,8 +78,8 @@ } } }, - "header": "0x2c80dc48494603ac15fa1ea88e3cd79565bdd54cf067a9bb4da9849870b60c690000000200000000000000000000000000000000000000000000000000000000000000029139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a90000000000000000000000000000000000000000000000000000000000000000c78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000002000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000002800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065f0698e66440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba", + "header": "0x02c6f1a862fd5dbef12bdeccfcc2bcf18a5c5b26c0465ac6470bc2c84e1626950000000200000000000000000000000000000000000000000000000000000000000000029139297703640b243028d35c29ae8c0667886c4edc8db5f879c260d2051bb8a9536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123cc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c1864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000002000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000002800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065f17e9b66440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba", "l1ToL2MessagesHash": "0x076a27c79e5ace2a3d47f9dd2e83e4ff6ea8872b3c2218f66c92b89b55f36560", - "publicInputsHash": "0x0fc84e6176557ac21fb1dd501d124270791bcd21474d814112b3ae4ed0c456bb" + "publicInputsHash": "0x151689d1af1478ba00ee16a4c21b6c4f61ecd7e1e71ad46870d5fd44c5759c23" } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_0.json b/l1-contracts/test/fixtures/mixed_block_0.json index 3ce256175e8..30ae66075ef 100644 --- a/l1-contracts/test/fixtures/mixed_block_0.json +++ b/l1-contracts/test/fixtures/mixed_block_0.json @@ -52,12 +52,12 @@ ] }, "block": { - "archive": "0x1ba503ae8f13b59815a58d204ca967063570ef165cb4d87b7609bce726f51410", + "archive": "0x002112631bea3a8334e954f4de111c9158cafeab265fc94ee695b3b4d20f0427", "body": "0x00000010151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d7839353703914c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a12806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e005f140c7c95624c8006774279a01ec1ea88617999e4fe6997b6576c4e1c7395a22048b96b586596bd740d0402e15f5577f7ceb5496b65aafc6d89d7c3b34924b0c3f2d50d16279970d682cada30bfa6b29bc0bac0ee2389f6a0444853eccaa932b2a60561da46a58569d71044a84c639e7f88429826e5622581536eb906d9cdd25a2c0a76f7da6924e10751c755227d2535f4ad258b984e78f9f452a853c52300e212d8e2069e4254d81af07744bcbb81121a38f0e2dbed69a523d3fbf85b75c287ca6f33aadbac2e4f058e05924c140d7895a6ed167caf804b710d2ae3ba62b1b51297b3ea37637af6bd56cf33425d95cc5c96e9c2ee3077322fbec86a0c7f32c15d2a888c6cc122e99478c92470a1311635142d82ad7ae67410beeef4ae31f0902ba2fb964922a4610bb18901f7b923885c1d034da5769a48203ae6f0206a92855e2c01ddb3d6553386b5580d681b8230fa4062948668f834f23e0636eaff70aaa64519aafdf4b040bd2f9836e76b9dc13cfec8065dcdf2834d786e06260d100000004380000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000014100000000000000000000000000000000000000000000000000000000000001420000000000000000000000000000000000000000000000000000000000000143000000000000000000000000000000000000000000000000000000000000014400000000000000000000000000000000000000000000000000000000000001450000000000000000000000000000000000000000000000000000000000000146000000000000000000000000000000000000000000000000000000000000014700000000000000000000000000000000000000000000000000000000000001480000000000000000000000000000000000000000000000000000000000000149000000000000000000000000000000000000000000000000000000000000014a000000000000000000000000000000000000000000000000000000000000014b000000000000000000000000000000000000000000000000000000000000014c000000000000000000000000000000000000000000000000000000000000014d000000000000000000000000000000000000000000000000000000000000014e000000000000000000000000000000000000000000000000000000000000014f0000000000000000000000000000000000000000000000000000000000000150000000000000000000000000000000000000000000000000000000000000015100000000000000000000000000000000000000000000000000000000000001520000000000000000000000000000000000000000000000000000000000000153000000000000000000000000000000000000000000000000000000000000015400000000000000000000000000000000000000000000000000000000000001550000000000000000000000000000000000000000000000000000000000000156000000000000000000000000000000000000000000000000000000000000015700000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000159000000000000000000000000000000000000000000000000000000000000015a000000000000000000000000000000000000000000000000000000000000015b000000000000000000000000000000000000000000000000000000000000015c000000000000000000000000000000000000000000000000000000000000015d000000000000000000000000000000000000000000000000000000000000015e000000000000000000000000000000000000000000000000000000000000015f0000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000001620000000000000000000000000000000000000000000000000000000000000163000000000000000000000000000000000000000000000000000000000000016400000000000000000000000000000000000000000000000000000000000001650000000000000000000000000000000000000000000000000000000000000166000000000000000000000000000000000000000000000000000000000000016700000000000000000000000000000000000000000000000000000000000001680000000000000000000000000000000000000000000000000000000000000169000000000000000000000000000000000000000000000000000000000000016a000000000000000000000000000000000000000000000000000000000000016b000000000000000000000000000000000000000000000000000000000000016c000000000000000000000000000000000000000000000000000000000000016d000000000000000000000000000000000000000000000000000000000000016e000000000000000000000000000000000000000000000000000000000000016f00000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000171000000000000000000000000000000000000000000000000000000000000017200000000000000000000000000000000000000000000000000000000000001730000000000000000000000000000000000000000000000000000000000000174000000000000000000000000000000000000000000000000000000000000017500000000000000000000000000000000000000000000000000000000000001760000000000000000000000000000000000000000000000000000000000000177370000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002730000000000000000000000000000000000000000000000000000000000000274000000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002760200000000000000000000000000000000000000000000000000000000000003400000000000000000000000000000000000000000000000000000000000000341100000000000000000000000000000000000000000000000000000000000000540000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000541000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000542000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000543000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000544000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000545000000000000000000000000000000000000000000000000000000000000054f00000000000000000000000000000000000000000000000000000000000005460000000000000000000000000000000000000000000000000000000000000550000000000000000000000000000000000000000000000000000000000000054700000000000000000000000000000000000000000000000000000000000005510000000000000000000000000000000000000000000000000000000000000548000000000000000000000000000000000000000000000000000000000000055200000000000000000000000000000000000000000000000000000000000005490000000000000000000000000000000000000000000000000000000000000553000000000000000000000000000000000000000000000000000000000000054a0000000000000000000000000000000000000000000000000000000000000554000000000000000000000000000000000000000000000000000000000000054b0000000000000000000000000000000000000000000000000000000000000555000000000000000000000000000000000000000000000000000000000000054c0000000000000000000000000000000000000000000000000000000000000556000000000000000000000000000000000000000000000000000000000000054d0000000000000000000000000000000000000000000000000000000000000557000000000000000000000000000000000000000000000000000000000000054e0000000000000000000000000000000000000000000000000000000000000558000000000000000000000000000000000000000000000000000000000000054f0000000000000000000000000000000000000000000000000000000000000559000011000000021c000000b02d622c8b62e54bf51a1fd35b67456b229dae3bc6126977f1b2d88662a3418347a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb6a83e0eb61b97deda6e3f6e57e02e3e50f41a6c05d9d508147d543e0d9fbbe858c33d4e6a2185f8c0152162e19e296fff1a7e1664c5c8194faf05fc0450c5725c0de96009000000b014b645af1d3b7df259bc545d7f52bc412546986a5f76ff3b331cb8dbddf1c9c2ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb6ac3e0eb602ebf7fe2895a0551fcabf530c27bd24616d64b8ca61c55720001ad1fded94e508da11e3cf7794deddc5f101328b67834d6075f3fc13834dd109a4d54899a684000000b02c6ead45b8c3501951a91b1618e165bcd512dd57263df715f742e0e908a2103eb03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb6b03e0eb61aa45f94c41d727c17b7860ba5b666a01139a9a59128bd31e42642df289ddb612092797a6aff6705d5b2b7b9cc1a10fefd2cbae0c2da7b28952fcce27349ed000000021c000000b013c2c6697319821691459c1830eeb6db5cab39fb734b7e5f77871362435256b9b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb6b43e0eb601f878b87e73a4795754070dbdc3b7be98d20649de36447b646a7558634e21dc07e6929e25559903154f38bbe427621d84c517850fe802721573ff5badfa337b000000b02b7b2e000ea1543d893262d0ca7d60570c777ee83a12763a3bad3b6f6e029d35b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb6b83e0eb619b0e04f19fb76a04f40cdc65752613a489e4b36a4fd3c5628909d658dfe68581f9efa34c0dd6b2a0d3bff747db60b9934915c71d6aefa4cd99a2768d8aa79f7000000b012cf4723c8f7863ac8cee3d2e28ab175940fdb8c871ffd83bbf16de8a8b2e3b0bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb6bc3e0eb60104f972d451a89d8edd4ec86f5fb258d036a7daf20ac39fa8d4cfdec8aeaed306f313587b339d274cd8807695c35cb7bc29b91623bc819659de59e2135ac0720000021c000000b02a87aeba647f5861c0bbaa8b7c195af143dc20794de6f55e801795f5d3632a2cc03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb6c03e0eb618bd61096fd97ac486ca158108ee5bd48002ecc7b8d1bb7a6cfaf7ebf35ef54f1eab7aef16bb6f4e44c5472f2f5206336bf5fe02ea8379711e0481ef3e0b06ee000000b011dbc7de1ed58a5f00582b8d9426ac0fcb747d1d9af47ca8005bc86f0e1370a7c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb6c43e0eb600117a2d2a2facc1c666968320fbacf3079b496c05df42c3ed3f2a652e0f3bca05ff9412d111a14b8461c831475f5751f38e5aa7379100ba9e48b46878bb4d69000000b029942f74ba5d5c85f844f2462db5558b7b40c20a61bb7482c481f07c38c3b723c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb6c83e0eb617c9e1c3c5b77ee8be535d3bba8a566eb7678e58cca63a9eb165527258bf82461db7fba96c9973727c4e8ee9e0ee00cda35a9f93fe57f895626edc75a36b93e50000021c000000b010e8489874b38e8337e1734845c2a6aa02d91eaeaec8fbcc44c622f57373fd9ecc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb6cc3e0eb62f82495a613f510fb64023f45418ffea6733d345936d3279758b7a7f836fc8c2050c14cd26efa56fbbeb0febf8fb51ec2af2fc384b657fdee2b30eeede1bda60000000b028a0b02f103b60aa2fce3a00df515025b2a5639b758ff3a708ec4b029e24441ad03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb6d03e0eb616d6627e1b95830cf5dca4f66c265108eecc2fe9e07ab9c2f5cfacf8be200f3d1cc47c63c2777796b3d7d6a49289fb67dabf4125122c77b9a6d936fc08cc20dc000000b00ff4c952ca9192a76f6abb02f75ea1443a3dc03fc29d7af089307d7bd8d48a95d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb6d43e0eb62e8eca14b71d5533edc96baf05b4fa849e9874d6a741b19db9f5d505e8d055b9041895877ccda993f37457a6aa974c8662579dc95f39ff03271d6975437c67570000021c000000b027ad30e9661964ce675781bb90ed4abfea0a052c896472cb4d56a5890384d111d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb6d83e0eb615e2e338717387312d65ecb11dc24ba32630d17af44f38e73a3a077f23809c341bd0fd1e18557bbaeb611e5f4425f6021223e2b62600f6ddeb4391826e2cadd3000000b00f014a0d206f96cba6f402bda8fa9bde71a261d0d671fa14cd9ad8023e35178cdc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb6dc3e0eb62d9b4acf0cfb59582552b369b750f51ed5fd1667bb1630c1fe602f8c4e30e2b003251641d2abadb82afd9f615c33472099bc3f5a730e7e276b87c3fba8dcf44e000000b026b9b1a3bbf768f29ee0c9764289455a216ea6bd9d38f1ef91c1000f68e55e08e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb6e03e0eb614ef63f2c7518b5564ef346bcf5e463d5d95730c0823b80b7ea4620588e1292b1add7dd86e337fdf22ea6619f5c1f09c4988844739d576022fadec08d38d3aca0000021c000000b00e0dcac7764d9aefde7d4a785a969678a9070361ea46793912053288a395a483e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb6e43e0eb62ca7cb8962d95d7c5cdbfb2468ecefb90d61b7f8ceeaafe642ca8a12b3916fa7023196fc2889b1dc6286e71c0dcf41bad120e0eb86e2fd4baff21e820e3d8145000000b025c6325e11d56d16d66a1130f4253ff458d3484eb10d7113d62b5a95ce45eaffe83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb6e83e0eb613fbe4ad1d2f8f799c787c2680fa40d794fa149d1bf8372fc30ebc8bee41b62219e9fe92c41184035a73add4a75deb3680ed25d84da9f5267418468f38edc7c1000000b00d1a4b81cc2b9f14160692330c329112e06ba4f2fe1af85d566f8d0f08f6317aec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb6ec3e0eb62bb44c43b8b761a0946542df1a88ea5344c65989e2bf2f0a8734e49918f1fc9e013e17b67e67b6009a102ed6bf6b3c550885827c9ab77c6ff45c7908739e0e3c0000021c000000b024d2b31867b3713b0df358eba5c13a8e9037e9dfc4e1f0381a95b51c33a677f6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb6f03e0eb613086567730d939dd401c3e132963b71cc5eb62e2fccb6540779171253a2431918f67f4d19ef882791fcf58f58f9e5d0b851c769617e744ab882a1159e4e54b8000000b00c26cc3c2209a3384d8fd9edbdce8bad17d0468411ef77819ad9e7956e56be71f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb6f43e0eb62ac0ccfe0e9565c4cbee8a99cc24e4ed7c2afb1af693ae2ecb9f3f1f7e528995004a9870d445ba24d1997691710736ef3fea240dae8bfb9438c6d38ed8fe9b33000000b023df33d2bd91755f457ca0a6575d3528c79c8b70d8b66f5c5f000fa2990704edf83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb6f83e0eb61214e621c8eb97c20b8b0b9be432360c03c357bf43a135784be37198b902d010180300076fcd8c4bc9863d4a0a95e06aefb668fa7552f36efcecfb9c03aee1af0000021c000000b00b334cf677e7a75c851921a86f6a86474f34e81525c3f6a5df44421bd3b74b68fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb6fc3e0eb629cd4db8647369e90377d2547dc0df87b38f9cac0a682d53100999a5e3b3168c2fbb679e0b555e72c1730402a42489e69f82ade73c19eb49c11323a92e5f282b000000b023533ea2e37804772c2110f02930ea449560b0aba9928ecbd3a6cb5f73909f15003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6003f0eb6112166dc1ec99be64314535695ce30a63b27f9505775b49c904dcc1f1e635d07170f80c1c5ab9070010f8504bc31db05271b0a8b8927729341575622690f6ea6000000b00aa757c69dce36746bbd91f2413e3b631cf90d4ff6a0161553eafdd8ae40e590043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6043f0eb6294158888a59f900ea1c429e4f9494a38153c1e6db444cc284b05562be3cb0b42f2f726e313bed8aa817744c75f83f026d46d3220cf60ab935b9df6608e8c25300000fa400000168000000b0225fbf5d3956089b63aa58aadacce4deccc5523cbd670df0181125e5d8f12c0c083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6083f0eb6109571ac44b02afe29b8c3a067a1e5c208ec1e8b2851d40c04f487dbf8ecf72f16838b91eb921f87e7b3f54e8e059020f4df2fc65a039202b5fe11df439908ce000000b009b3d880f3ac3a98a346d9acf2da35fd545daee10a7495399855585f13a172870c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb60c3f0eb6284dd942e037fd2521a58a5901308f3db8b86377ef18cbe6c91aafe9239d3dab2e3bf3288719f1aedfa0bc072794399ca4ab74b320ca89dd7a2439ec6e494f4a00000168000000b0216c40178f340cbf9b33a0658c68df790429f3cdd13b8d145c7b806c3e51b903103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb6103f0eb60fa1f2669a8e2f2261420b5b193de05c4050c01c3c265330495ee2625e4d842615900c4c417023ac1f3d3d093fa18abb2c43d1576dd81126fa686c65a8f995c5000000b008c0593b498a3ebcdad02167a47630978bc250721e49145ddcbfb2e57901ff7e143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6143f0eb6275a59fd36160149592ed213b2cc89d7f01d050902ed4b0b0d850a6f88fdcaa22d4873e2dcf7f5d3172a03c1d9303436dc101644349f0901be8e9472d3a9dc4100000168000000b02078c0d1e51210e3d2bce8203e04da133b8e955ee5100c38a0e5daf2a3b245fa183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb6183f0eb60eae7320f06c334698cb5315cad9daf677b561ad4ffad2548dc93ce8c3ae111d149c8d06974e27d056c684c3f13d855563a872e881ac904b3ed2c6ec0e5a22bc000000b007ccd9f59f6842e11259692256122b31c326f203321d9382212a0d6bde628c751c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb61c3f0eb62666dab78bf4056d90b819ce646884722781a69a16c1ca2f51ef64f5ee5e57992c54f49d32d5f9f74eb34b7c8acc2ed11374b7d54873882602f8eef9390a693800000168000000b01f85418c3af015080a462fdaefa0d4ad72f336eff8e48b5ce55035790912d2f1203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb6203f0eb60dbaf3db464a376ad0549ad07c75d590af1a033e63cf5178d233976f290e9e1413a90dc0ed2c2bf48e4fcc7ea2d97fef9b0d147995810f6f833d217273baafb3000000b006d95aaff546470549e2b0dd07ae25cbfa8b939445f212a6659467f243c3196c243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb6243f0eb625735b71e1d20991c841618916047f0c5ee6482b2a9649539659bf7c53bee4902b61755788b3fe1b863c93373c68296b4ad959665c48074a4763497f9e6af62f00000168000000b01e91c24690ce192c41cf7795a13ccf47aa57d8810cb90a8129ba8fff6e735fe8283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb6283f0eb60cc774959c283b8f07dde28b2e11d02ae67ea4cf77a3d09d169df1f58e6f2b0b12b58e7b430a3018c5d9143954757a89d271b60aa9558e93c7a77bf8d91b3caa000000b005e5db6a4b244b29816bf897b94a206631f0352559c691caa9fec278a923a6632c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb62c3f0eb6247fdc2c37b00db5ffcaa943c7a079a6964ae9bc3e6ac877dac41a02b91f71872a6df611de92023fbdc5daf1ee042405823dfaf7701c866e8bcda40603cb832600000168000000b01d9e4300e6ac1d507958bf5052d8c9e1e1bc7a12208d89a56e24ea85d3d3ecdf303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb6303f0eb60bd3f54ff2063fb33f672a45dfadcac51de346608b784fc15b084c7bf3cfb80211c20f3598e8343cfd625bf40611752409d6579bbd2a0db80c11d67f3e7bc9a1000000b004f25c24a1024f4db8f540526ae61b006954d6b66d9b10eeee691cff0e84335a343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6343f0eb6238c5ce68d8e11da3753f0fe793c7440cdaf8b4d523f479c1f2e74891e7ffe7e297a76cc34700663f54f22ac9fa01e9fb9a29c8883f10592d037fe8c692c101d00000168000000b01caac3bb3c8a2174b0e2070b0474c47c19211ba3346208c9b28f450c393479d6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb6383f0eb60ae0760a47e443d776f072009149c55f5547e7f19f4ccee59f72a702593044f910ce8fefeec6386134eba3aeb7ad6fbe413af92cd0fe8cdc507c3105a3dc5698000000b003fedcdef6e05371f07e880d1c82159aa0b97847816f901332d3778573e4c0513c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb63c3f0eb62298dda0e36c15fe6edd38b92ad86edb05142cde6613c6c06398cf0f83e08b752886f7868a4e0a882cd86a67513c1939f1073e1997c584b714a25912ce8c9d1400000168000000b01bb7447592682598e86b4ec5b610bf165085bd34483687edf6f99f929e9506cd403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb6403f0eb609ecf6c49dc247fbae79b9bb42e5bff98cac8982b3214e09e3dd0188be90d1f00fdb10aa44a43c856c74eb6969496a58789f9abde4d30c0094e68b8c093ce38f000000b0030b5d994cbe57962807cfc7ce1e1034d81e19d895440f37773dd20bd9454d48443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb6443f0eb621a55e5b394a1a22a6668073dc7469753c78ce6f79e845e4a8032995e941186c27937840e02c0eac6461b22202d813d4286bdfaaab9a03db590cb39933ed2a0b00000168000000b01ac3c52fe84629bd1ff4968067acb9b087ea5ec55c0b07123b63fa1903f593c4483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb6483f0eb608f9777ef3a04c1fe6030175f481ba93c4112b13c6f5cd2e28475c0f23f15ee70ee791649a8240a9a3fe33241ae564f2b0043c4ef8a78b24d950e6126e9d7086000000b00217de53a29c5bba5f9117827fba0acf0f82bb69a9188e5bbba82c923ea5da3f4c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb64c3f0eb620b1df158f281e46ddefc82e8e10640f73dd70008dbcc508ec6d841c4ea1a563269ff8fb360a12d09beaf9dcb4740e6e5fd0813bbf6e82ff9d770e1f994db70200000168000000b019d045ea3e242de1577dde3b1948b44abf4f00566fdf86367fce549f695620bb503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb6503f0eb60805f839497e50441d8c4930a61db52dfb75cca4daca4c526cb1b6958951ebde0df4121ef06044cddb877adecc815f8ce768dde00c7c0a491dbb4098d3fdfd7d000000b001245f0df87a5fde971a5f3d3156056946e75cfabced0d8000128718a4066736543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb6543f0eb61fbe5fcfe506226b15790fe93fac5ea9ab421191a191442d30d7dea2b402325a25ac79b58be816f4d374419766100908973522ccd3430223e1e168a5feae43f900000168000000b018dcc6a4940232058f0725f5cae4aee4f6b3a1e783b4055ac438af25ceb6adb2583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6583f0eb6071278f39f5c5468551590eb57b9afc832da6e35ee9ecb76b11c111beeb278d50d0092d9463e48f21310c2997e1d5a271ecd7f712050896d62259b1f395e8a74000000b00030dfc84e586402cea3a6f7e2f200037e4bfe8bd0c18ca4447ce19f0966f42d5c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb65c3f0eb61ecae08a3ae4268f4d0257a3f1485943e2a6b322b565c351754239291962bf5124b8fa6fe1c61b190afd895217ac03a2ce99c45de7178148264bc32c640ed0f0380000000000000000000000000000000000000000000000000000000000000180000000000000000000000000000000000000000000000000000000000000018100000000000000000000000000000000000000000000000000000000000001820000000000000000000000000000000000000000000000000000000000000183000000000000000000000000000000000000000000000000000000000000018400000000000000000000000000000000000000000000000000000000000001850000000000000000000000000000000000000000000000000000000000000186000000000000000000000000000000000000000000000000000000000000018700000000000000000000000000000000000000000000000000000000000001880000000000000000000000000000000000000000000000000000000000000189000000000000000000000000000000000000000000000000000000000000018a000000000000000000000000000000000000000000000000000000000000018b000000000000000000000000000000000000000000000000000000000000018c000000000000000000000000000000000000000000000000000000000000018d000000000000000000000000000000000000000000000000000000000000018e000000000000000000000000000000000000000000000000000000000000018f0000000000000000000000000000000000000000000000000000000000000190000000000000000000000000000000000000000000000000000000000000019100000000000000000000000000000000000000000000000000000000000001920000000000000000000000000000000000000000000000000000000000000193000000000000000000000000000000000000000000000000000000000000019400000000000000000000000000000000000000000000000000000000000001950000000000000000000000000000000000000000000000000000000000000196000000000000000000000000000000000000000000000000000000000000019700000000000000000000000000000000000000000000000000000000000001980000000000000000000000000000000000000000000000000000000000000199000000000000000000000000000000000000000000000000000000000000019a000000000000000000000000000000000000000000000000000000000000019b000000000000000000000000000000000000000000000000000000000000019c000000000000000000000000000000000000000000000000000000000000019d000000000000000000000000000000000000000000000000000000000000019e000000000000000000000000000000000000000000000000000000000000019f00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001a100000000000000000000000000000000000000000000000000000000000001a200000000000000000000000000000000000000000000000000000000000001a300000000000000000000000000000000000000000000000000000000000001a400000000000000000000000000000000000000000000000000000000000001a500000000000000000000000000000000000000000000000000000000000001a600000000000000000000000000000000000000000000000000000000000001a700000000000000000000000000000000000000000000000000000000000001a800000000000000000000000000000000000000000000000000000000000001a900000000000000000000000000000000000000000000000000000000000001aa00000000000000000000000000000000000000000000000000000000000001ab00000000000000000000000000000000000000000000000000000000000001ac00000000000000000000000000000000000000000000000000000000000001ad00000000000000000000000000000000000000000000000000000000000001ae00000000000000000000000000000000000000000000000000000000000001af00000000000000000000000000000000000000000000000000000000000001b000000000000000000000000000000000000000000000000000000000000001b100000000000000000000000000000000000000000000000000000000000001b200000000000000000000000000000000000000000000000000000000000001b300000000000000000000000000000000000000000000000000000000000001b400000000000000000000000000000000000000000000000000000000000001b500000000000000000000000000000000000000000000000000000000000001b600000000000000000000000000000000000000000000000000000000000001b7370000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b60200000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000381100000000000000000000000000000000000000000000000000000000000000580000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000581000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000582000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000583000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000584000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000585000000000000000000000000000000000000000000000000000000000000058f00000000000000000000000000000000000000000000000000000000000005860000000000000000000000000000000000000000000000000000000000000590000000000000000000000000000000000000000000000000000000000000058700000000000000000000000000000000000000000000000000000000000005910000000000000000000000000000000000000000000000000000000000000588000000000000000000000000000000000000000000000000000000000000059200000000000000000000000000000000000000000000000000000000000005890000000000000000000000000000000000000000000000000000000000000593000000000000000000000000000000000000000000000000000000000000058a0000000000000000000000000000000000000000000000000000000000000594000000000000000000000000000000000000000000000000000000000000058b0000000000000000000000000000000000000000000000000000000000000595000000000000000000000000000000000000000000000000000000000000058c0000000000000000000000000000000000000000000000000000000000000596000000000000000000000000000000000000000000000000000000000000058d0000000000000000000000000000000000000000000000000000000000000597000000000000000000000000000000000000000000000000000000000000058e0000000000000000000000000000000000000000000000000000000000000598000000000000000000000000000000000000000000000000000000000000058f0000000000000000000000000000000000000000000000000000000000000599000011000000021c000000b017e9475ee9e03629c6906db07c80a97f2e1843789788847f08a309ac34173aa9603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6603f0eb6061ef9adf53a588c8c9ed8a60955aa626a3f0fc702734a9af5866ba2541305cc0c0d13939c1c4d164a9a0a542fb954c15632210234250891a68ff5a59ebf176b000000b02fa1aef585680850be7d3469160f52fadde488655e4f7c59ccc931b95ec78125643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb6643f0eb61dd7614490c22ab3848b9f5ea2e453de1a0b54b3c93a4275b9ac93af7ec34c4823c57b2a37a41f3d4286d10cc947fe3d05fe65eefaec006c6ab61db2c96f5de7000000b016f5c8193fbe3a4dfe19b56b2e1ca419657ce509ab5d03a34d0d64329977c7a0683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6683f0eb6052b7a684b185cb0c4282060baf1a4fca1a3b1581647c9bf39f0c628b97392c30b19944df1fa513a8223520ee1554f5b8d96c29347f987b5eafa502c041fa4620000021c000000b02eae2fafdb460c74f6067c23c7ab4d95154929f67223fb7e11338c3fc4280e1c6c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb66c3f0eb61ce3e1fee6a02ed7bc14e71954804e78516ff644dd0ec199fe16ee35e423d93f22d1fbe48d8223617a1018c77ae3f8d73d6307800ec07f90af2078392ecfeade000000b0160248d3959c3e7235a2fd25dfb89eb39ce1869abf3182c79177beb8fed85497703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb6703f0eb60437fb22a0f660d4fbb1681b6c8d9f96d90852e92a1c48e37e5b20af1ed41fba0a26150847d8555eb9ac99c992f149f5c4fb64245bce06da2f64aab269803159000000b02dbab06a312410992d8fc3de7947482f4cadcb8785f87aa2559de6c629889b13743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb6743f0eb61bf062b93c7e32fbf39e2ed4061c491288d497d5f0e340be428148bc4984663621de7c9ee3602785b19960822c7ff37174c7a9112294feb4f38ad2bf943077d50000021c000000b0150ec98deb7a42966d2c44e09154994dd446282bd30601ebd5e2193f6438e18e783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb6783f0eb603447bdcf6d464f9333aafd61e299a31106cf47a3df0c807c2c57b358434acb1093295c29db65982f135e184448d448ffc6005b56fa285fe73cf0538cee0be50000000b02cc73124870214bd65190b992ae342c984126d1899ccf9c69a08414c8ee9280a7c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb67c3f0eb61afce373925c37202b27768eb7b843acc039396704b7bfe286eba342aee4f32d20eafd59393e2ba9e922a83cde1bee0bac2c4aa236697dd937f52d45f99104cc000000b0141b4a48415846baa4b58c9b42f093e80baac9bce6da81101a4c73c5c9996e85803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb6803f0eb60250fc974cb2691d6ac3f790cfc594cb47d1960b51c5472c072fd5bbe99539a8083f167cf3945da728bf293ef6293f2a33c4a74683770522b8395fbf34414b470000021c000000b02bd3b1dedce018e19ca25353dc7f3d63bb770ea9ada178eade729bd2f449b501843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb6843f0eb61a09642de83a3b4462b0be4969543e46f79ddaf8188c3f06cb55fdc9144580241ff77e138f1c2fce20abeff78fb7e8a5e390ec334a3dfcfd7c5f87cc5ef191c3000000b01327cb0297364adedc3ed455f48c8e82430f6b4dfaaf00345eb6ce4c2ef9fb7c883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6883f0eb6015d7d51a2906d41a24d3f4b81618f657f36379c6599c6504b9a30424ef5c69f074b9737497261cb604870f9a7c539c46b2948d7974b8446fca3ba4599a1d83e000000b02ae0329932be1d05d42b9b0e8e1b37fdf2dbb03ac175f80f22dcf65959aa41f88c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb68c3f0eb61915e4e83e183f689a3a06041af038e12f027c892c60be2b0fc0584f79a60d1b1f03fecde4fa33f2583537b24153e3401af58dc45e127c21c0c9e252c4521eba0000021c000000b012344bbced144f0313c81c10a628891c7a740cdf0e837f58a32128d2945a8873903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb6903f0eb60069fe0bf86e7165d9d6870632fd89ffb69ad92d796e457490048ac8b4565396065817f19f5065ef97d1b8b45961345ea28dea68ab20036b410e14cbff026535000000b029ecb353889c212a0bb4e2c93fb732982a4051cbd54a7733674750dfbf0aceef943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6943f0eb6182265a293f6438cd1c34dbecc8c337b66671e1a40353d4f542ab2d5df069a121e107f883ad838168fbe7f6cf2efddda525a2f5571e6fb4605343cd929b2abb1000000b01140cc7742f253274b5163cb57c483b6b1d8ae702257fe7ce78b8358f9bb156a983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb6983f0eb62fdacd392f7e15b3c9b01477661adcf71633630706fc352a1850dae309b6e08e056498abf52e6a13cf5b006f0afd2ef8d9f28bf9bef4828f85786f526462f22c0000021c000000b028f9340dde7a254e433e2a83f1532d3261a4f35ce91ef657abb1ab66246b5be69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb69c3f0eb6172ee65ce9d447b1094c95797e282e159dcbbfab5409bc7398950d5c446727091d1d004290b63c3ac747c727a48bd87489bed0e685bb7a6a499e975f8f1338a8000000b0104d4d3198d0574b82daab8609607e50e93d5001362c7da12bf5dddf5f1ba261a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb6a03f0eb62ee74df3855c19d801395c3217b6d7914d9804981ad0b44e5cbb35696f176d85047119664b0c6e3806e44829bc99299311572d8ad2c901b3c9e2c9d8c9c37f23000000b02805b4c8345829727ac7723ea2ef27cc990994edfcf3757bf01c05ec89cbe8dda43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6a43f0eb6163b67173fb24bd540d5dd342fc428afd530613c67de3b97dcff67e2a9c7b4001c2980fce694405efed10ee25627d30ec1237277998ff98e8e08f1e5f473c59f0000021c000000b00f59cdebeeae5b6fba63f340bafc78eb20a1f1924a00fcc570603865c47c2f58a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb6a83f0eb62df3ceaddb3a1dfc38c2a3ecc952d22b84fca6292ea53372a1258fefd477fa7c037d9a20a0ea725c3e6d8fe46e35242d48bbcf1be69d80d80e4d245f2f240c1a000000b0271235828a362d96b250b9f9548b2266d06e367f10c7f4a034866072ef2c75d4ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb6ac3f0eb61547e7d195904ff9785f24eee160234a0c9502cd7bb2babc2169c2690f2840f71b3601b73c724483365a569d07c3cda8f8881408ad6478b2d2734c6c59d45296000000b00e664ea6448c5f93f1ed3afb6c987385580693235dd57be9b4ca92ec29dcbc4fb03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb6b03f0eb62d004f6831182220704beba77aeeccc5bc6147ba4279b296e58fea7639d88773028a1adaf6c8768075f6d79f1fd11ec7802070acfa71fffc52b77ee5948499110000021c000000b0261eb63ce01431bae9da01b406271d0107d2d810249c73c478f0baf9548d02cbb43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb6b43f0eb61454688beb6e541dafe86ca992fc1de443f9a45e8f8739e065d41cef7488cdee1a428271925048a76de39e57b95fc8432fecb599c138f7d716dda6f2bf34df8d000000b00d72cf609a6a63b8297682b61e346e1f8f6b34b471a9fb0df934ed728f3d4946b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb6b83f0eb62c0cd02286f62644a7d533622c8ac75ff3c5e94b564e31bb29fa44fc9f39146a01969b954ca67aa4ad801f59d16d1961b785123e0e467f209721d96bf9e52608000000b0252b36f735f235df2163496eb7c3179b3f3779a13870f2e8bd5b157fb9ed8fc2bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb6bc3f0eb61360e946414c5841e771b4644498187e7b5e45efa35bb904aa3e7775d9e95ae5194f032be82e4ccba56ce6126afbc2dd6751572ad50d76fb5b48017924956c8400000fa400000168000000b00c7f501af04867dc60ffca70cfd068b9c6cfd645857e7a323d9f47f8f49dd63dc03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb6c03f0eb62b1950dcdcd42a68df5e7b1cde26c1fa2b2a8adc6a22b0df6e649f830499a16100a31c4fa2847ec8e5096714830913fbeee9b3cf221afe44db8c33f25f45b2ff000000b02437b7b18bd03a0358ec9129695f1235769c1b324c45720d01c570061f4e1cb9c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6c43f0eb6126d6a00972a5c661efafc1ef6341318b2c2e780b7303828eea8d1fc3f49e7dc185b83e63e0c50efdcf62dcd1c97bd779eb5f8bbe8e1f61f9fb25bff89f5f97b00000168000000b00b8bd0d546266c009889122b816c6353fe3477d69952f9568209a27f59fe6334c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb6c83f0eb62a25d19732b22e8d16e7c2d78fc2bc94628f2c6d7df73003b2cefa0969fa2e583013eb7cd9942316d4e2f485b62666f34e823da8afa8edfa63d8840cb4a63ff7000000b02344386be1ae3e279075d8e41afb0ccfae00bcc36019f131462fca8c84aea9b0cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb6cc3f0eb61179eabaed08608a568443d9a7d00db2ea278911cb04b74d33132c82a4aa74d3176804a093ea5514147f7587ce33b811d61a9a4cfcb67543e41cb685ef56867200000168000000b00a98518f9c047024d01259e633085dee35991967ad27787ac673fd05bf5ef02bd03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb6d03f0eb629325251889032b14e710a92415eb72e99f3cdfe91cbaf27f739548fcf5abb4f2f206c372f72273b0c6c3c4067c2618d85e6df39c37d6d1ea842de931a06ccee000000b02250b926378c424bc7ff209ecc970769e5655e5473ee70558a9a2512ea0f36a7d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb6d43f0eb610866b7542e664ae8e0d8b94596c084d218c2aa2ded93671777d87090a0b01ca1674855ae9c859384c08bd427fcfb2ac0d7f3bde108af4682887110c54b7136900000168000000b009a4d249f1e27449079ba1a0e4a458886cfdbaf8c0fbf79f0ade578c24bf7d22d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6d83f0eb6283ed30bde6e36d585fa524cf2fab1c8d1586f8fa5a02e4c3ba3af1634bb48462e2cecf185502b5f43f583fb195e5c27bd4b80cad751ec42ecad39197f6759e5000000b0215d39e08d6a466fff8868597e3302041cc9ffe587c2ef79cf047f994f6fc39edc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb6dc3f0eb60f92ec2f98c468d2c596d34f0b0802e758f0cc33f2adb595bbe7e18f6f6b8ec1158106153fa65d5c839204fd316bad4644e3dd6f245f738c6cf16b92ba17a06000000168000000b008b1530447c0786d3f24e95b96405322a4625c89d4d076c34f48b2128a200a19e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6e03f0eb6274b53c6344c3af9bd839a07a496ac6308bd1120b974ad70800e099c9a1bd53d2d396dabdb2e2f837b7ecbb5cafa56c1f4b0225beb266b673117939fe4c7e6dc000000b02069ba9ae3484a943711b0142fcefc9e542ea1769b976e9e136eda1fb4d05095e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb6e43f0eb60e9f6ce9eea26cf6fd201b09bca3fd8190556dc5068234ba00523c15d4cc1bb8148d86cf95846180bb1b4cb7e307a7e07c487f003833f2b0b15bc6191f782d5700000168000000b007bdd3be9d9e7c9176ae311647dc4dbcdbc6fe1ae8a4f5e793b30c98ef809710e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb6e83f0eb62657d4808a2a3f1df50ce1c25632a6fd4021b2b1cd492c94c4786422ff7c62342c45ee66310c33a7b30813707c96515c2c14c3ecfefaea8b7581ee264a2873d3000000b01f763b5539264eb86e9af7cee16af7388b934307af6bedc257d934a61a30dd8cec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb6ec3f0eb60dabeda44480711b34a962c46e3ff81bc7ba0f561a56b3de44bc969c3a2ca8af139a0789eb6265a4f2a4947294a3a27ab3ad20914c0871d4f5c6209f84d8ba4e00000168000000b006ca5478f37c80b5ae3778d0f9784857132b9fabfc79750bd81d671f54e12407f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb6f03f0eb62564553ae00843422c96297d07cea19777865442e11dabb908e2bea964dcef2b2b526f2086ea37cbea915b2b2e324bf66379657e12cf69afb9ec48acaf8900ca000000b01e82bc0f8f0452dca6243f899306f1d2c2f7e498c3406ce69c438f2c7f916a83f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb6f43f0eb60cb86e5e9a5e753f6c32aa7f1fdbf2b5ff1eb0e72e2b33028926f1229f8d35a612a68844414069c92a2ddc2d463f9d14eb11c2225fdcf0f93a307b25ea39474500000168000000b005d6d533495a84d9e5c0c08bab1442f14a90413d104df4301c87c1a5ba41b0fef83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb6f83f0eb62470d5f535e64766641f7137b96a9c31aeeaf5d3f4f22add4d4d192fca3d7c222a5eefdadcc83bf0221aa2e5dfce46909ade070f26a3e8d3fe56a33314e98dc1000000b01d8f3cc9e4e25700ddad874444a2ec6cfa5c8629d714ec0ae0ade9b2e4f1f77afc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb6fc3f0eb60bc4ef18f03c7963a3bbf239d177ed503683527841ffb226cd914ba904edc29d11b308fe971e6ded61b723e7f7db97af227663b373b1701d7e9ad5ac4f99d43c00000168000000b0054ae0036f4113f1cc6530d57ce7f80d18546677e12a139f912e7d6294cb4b2600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb600400eb6237d56af8bc44b8a9ba8b8f26b0696cbe64f976508c6aa0191b773b62f9e0919296b709532a6401459a3eaa0916a412ad242a8a03a7867f842c0fdb97a4a1ab8000000b01d03479a0ac8e618c451f78e1676a188c820ab64a7f10b7a5554a56fbf7b91a204400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb604400eb60b38f9e91623087b8a606283a34ba26c044777b312dbd19642380765df775cc5112713cebd04fd05485b9431c9af4ccaf03a88ee448d8f8cf34191692a236e6400000168000000b0045760bdc51f181603ee78902e83f2a74fb90808f4fe92c3d598d7e8fa2bd81d08400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb608400eb622f1617fb1aadaa2824d293c3cda4be7b413bc9fd9a2c971065e2f730a27a34128df7b65588ccf2c40485aea633df646a006cddb0b548767b767b97654d3b4e0000000b01c0fc85460a6ea3cfbdb3f48c8129c22ff854cf5bbc58a9e99befff624dc1e990c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60c400eb60a457aa36c010c9fc1e9aa3e54e79d063bac194426b050ba86a261ec44d7e9bc1033948912e301297fe4dbec7b4b4765279f2a7f58620eb137abebef8f83fb5b00000168000000b00363e1781afd1c3a3b77c04ae01fed41871da99a08d311e81a03326f5f8c651410400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb610400eb621fde23a0788dec6b9d670f6ee764681eb785e30ed7748954ac889f96f88303827ebfc1fae6ad35077d1a2a514d9f0e0d76b6f6c1f29068bfbd213fcba3441d7000000b01b1c490eb684ee613364870379ae96bd36e9ee86cf9a09c2de295a7c8a3cab9014400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb614400eb60951fb5dc1df10c3f972f1f9068397a07310bad53a84cfdecb0cbc72aa3876b30f40154368c1054db76e23a72ce741ff5f03cc106c368dd57c164675f4e488523800000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c300000000000000000000000000000000000000000000000000000000000001c400000000000000000000000000000000000000000000000000000000000001c500000000000000000000000000000000000000000000000000000000000001c600000000000000000000000000000000000000000000000000000000000001c700000000000000000000000000000000000000000000000000000000000001c800000000000000000000000000000000000000000000000000000000000001c900000000000000000000000000000000000000000000000000000000000001ca00000000000000000000000000000000000000000000000000000000000001cb00000000000000000000000000000000000000000000000000000000000001cc00000000000000000000000000000000000000000000000000000000000001cd00000000000000000000000000000000000000000000000000000000000001ce00000000000000000000000000000000000000000000000000000000000001cf00000000000000000000000000000000000000000000000000000000000001d000000000000000000000000000000000000000000000000000000000000001d100000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001d300000000000000000000000000000000000000000000000000000000000001d400000000000000000000000000000000000000000000000000000000000001d500000000000000000000000000000000000000000000000000000000000001d600000000000000000000000000000000000000000000000000000000000001d700000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001d900000000000000000000000000000000000000000000000000000000000001da00000000000000000000000000000000000000000000000000000000000001db00000000000000000000000000000000000000000000000000000000000001dc00000000000000000000000000000000000000000000000000000000000001dd00000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001df00000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000001e100000000000000000000000000000000000000000000000000000000000001e200000000000000000000000000000000000000000000000000000000000001e300000000000000000000000000000000000000000000000000000000000001e400000000000000000000000000000000000000000000000000000000000001e500000000000000000000000000000000000000000000000000000000000001e600000000000000000000000000000000000000000000000000000000000001e700000000000000000000000000000000000000000000000000000000000001e800000000000000000000000000000000000000000000000000000000000001e900000000000000000000000000000000000000000000000000000000000001ea00000000000000000000000000000000000000000000000000000000000001eb00000000000000000000000000000000000000000000000000000000000001ec00000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001ee00000000000000000000000000000000000000000000000000000000000001ef00000000000000000000000000000000000000000000000000000000000001f000000000000000000000000000000000000000000000000000000000000001f100000000000000000000000000000000000000000000000000000000000001f200000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f500000000000000000000000000000000000000000000000000000000000001f600000000000000000000000000000000000000000000000000000000000001f73700000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f60200000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c11000000000000000000000000000000000000000000000000000000000000005c000000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005c100000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005c200000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005c300000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005c400000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005c500000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005c600000000000000000000000000000000000000000000000000000000000005d000000000000000000000000000000000000000000000000000000000000005c700000000000000000000000000000000000000000000000000000000000005d100000000000000000000000000000000000000000000000000000000000005c800000000000000000000000000000000000000000000000000000000000005d200000000000000000000000000000000000000000000000000000000000005c900000000000000000000000000000000000000000000000000000000000005d300000000000000000000000000000000000000000000000000000000000005ca00000000000000000000000000000000000000000000000000000000000005d400000000000000000000000000000000000000000000000000000000000005cb00000000000000000000000000000000000000000000000000000000000005d500000000000000000000000000000000000000000000000000000000000005cc00000000000000000000000000000000000000000000000000000000000005d600000000000000000000000000000000000000000000000000000000000005cd00000000000000000000000000000000000000000000000000000000000005d700000000000000000000000000000000000000000000000000000000000005ce00000000000000000000000000000000000000000000000000000000000005d800000000000000000000000000000000000000000000000000000000000005cf00000000000000000000000000000000000000000000000000000000000005d9000011000000021c000000b00270623270db205e7301080591bbe7dbbe824b2b1ca7910c5e6d8cf5c4ecf20b18400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb618400eb6210a62f45d66e2eaf15fb8b1a012411c22dcffc2014bc7b98f32e47fd4e8bd2f26f87cda0448d774af5aea5fc675eb7b0ed010fd32fd85b0403c6e831f94cece000000b01a28c9c90c62f2856aedcebe2b4a91576e4e9017e36e88e72293b502ef9d38871c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb61c400eb6085e7c1817bd14e830fc39b3b81f923aaa755c664e594f030f7716f90f9903aa0e4c95fdbe9f0971eef76b61de833c9996686da1800b0cf9c080a0fc5a451549000000b0017ce2ecc6b92482aa8a4fc04357e275f5e6ecbc307c1030a2d7e77c2a4d7f0220400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb620400eb62016e3aeb344e70f28e9006c51ae3bb65a41a153152046ddd39d3f063a494a262604fd945a26db98e6e4321a7811e6154634b28e46d204d484a6c90984f55bc50000021c000000b019354a836240f6a9a2771678dce68bf1a5b331a8f743080b66fe0f8954fdc57e24400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb624400eb6076afcd26d9b190c6885816e69bb8cd4e1d9fdf7622dce2753e1717f74f990a10d5916b8147d0d962680b31c901f3733cdcd0f3293df8c1e04eafb82bfa5a240000000b0008963a71c9728a6e213977af4f3dd102d4b8e4d44508f54e74242028fae0bf928400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb628400eb61f2364690922eb3360724827034a365091a642e428f4c6021807998c9fa9d71d25117e4eb004dfbd1e6d79d529ade0af7d99541f5aa683f8c911238fea55e8bc000000b01841cb3db81efacdda005e338e82868bdd17d33a0b17872fab686a0fba5e52752c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb62c400eb606777d8cc3791d30a00ec9291b57876f193e9f8876024d4b984bcc05da5a1d980c6597726a5b11ba5e09fad741bb31ce0531b0c3a7b40b424955560925062f370000021c000000b02ffa32d453a6ccf4d1ed24ec281130078ce41826d1de7f0a6f8e921ce50e98f130400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb630400eb61e2fe5235f00ef5797fb8fe1b4e630eac90ae4753cc945265c71f413050a6414241dff0905e2e3e155f6c18fdb49db49b4fdf5b06e7b031d0d7b7e164fb675b3000000b0174e4bf80dfcfef21189a5ee401e8126147c74cb1eec0653efd2c4961fbedf6c34400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb634400eb60583fe4719572154d79810e3ccf3820950a3411989d6cc6fdcb6268c3fbaaa8f0b72182cc03915de95934291f3572c683c965254bb888a668dbfb08f8a66bc2e000000b02f06b38ea984d11909766ca6d9ad2aa1c448b9b7e5b2fe2eb3f8eca34a6f25e838400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb638400eb61d3c65ddb4def37bcf84d79c66822b85006f8606509dc44aa0dc4e996a6af10b232a7fc35bc0e8058d80094a8ce5d5e3ec629741824f824151e5d89cb51702aa0000021c000000b0165accb263db03164912eda8f1ba7bc04be1165c32c08578343d1f1c851f6c633c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb63c400eb604907f016f3525790f21589e7e8f7ca38807e2aa9dab4b9421208112a51b37860a7e98e716171a02cd1c8a4ca4f3270273faf3e5cf5d098ad22a0b15efc74925000000b02e133448ff62d53d40ffb4618b49253bfbad5b48f9877d52f8634729afcfb2df40400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb640400eb61c48e6980abcf7a0070e1f57181e261f37d427976472436ee546a91fcfcb7e022237007db19eec29c50951053e81d07e23c738d296240165965033231a778fa1000000b015674d6cb9b9073a809c3563a356765a8345b7ed4695049c78a779a2ea7ff95a44400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb644400eb6039cffbbc513299d46aaa059302b773dbf6c843bb17fcab8658adb990a7bc47d098b19a16bf51e2704a5d207568f219cab5f9576e33188af1694659c5527d61c0000021c000000b02d1fb5035540d9617888fc1c3ce51fd63311fcda0d5bfc773ccda1b015303fd648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb648400eb61b556752609afbc43e976711c9ba20b96f38c9287846c29329b103a6352c0af921438138077cf04dfc9298bff01dcb185b2bda63a9f88089daba8da97fd81c98000000b01473ce270f970b5eb8257d1e54f270f4baaa597e5a6983c0bd11d4294fe086514c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb64c400eb602a980761af12dc17e33e813e1c771d7f6d125ccc55449dca9f5361f6fdc517408979a5bc1d3224b3c2f19c2082b1c36e2c43707f70607d35afec022ba886313000000b02c2c35bdab1edd85b01243d6ee811a706a769e6b21307b9b8137fc367a90cccd50400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb650400eb61a61e80cb678ffe87620aecc7b561b53a69d6ab98c1b41b76e1b5e2c9a8c97f0205001f25d5af472341be07aa1b9c5b292907bf4bdccffae1f24e82fe538a98f0000021c000000b013804ee165750f82efaec4d9068e6b8ef20efb0f6e3e02e5017c2eafb541134854400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb654400eb601b6013070cf31e5b5bd2fce93636c722e35c75dd928c900ee5f90a5d53cde6b07a41b1617b1266f73b8617cb9c716d11a28d8990ada86f79f691aa91fe8f00a000000b02b38b67800fce1a9e79b8b91a01d150aa1db3ffc3504fabfc5a256bcdff159c458400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb658400eb6196e68c70c57040cada9f6872cf215edde020c4a9fefc0dbb285b8b2ffed24e71f5c82acb338f8966ba528355355c04cc9f51d85d1a17ed2638f42b64a993686000000b0128ccf9bbb5313a727380c93b82a662929739ca08212820945e689361aa1a03f5c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb65c400eb600c281eac6ad3609ed46778944ff670c659a68eeecfd482532c9eb2c3a9d6b6206b09bd06d8f2a93ab41a9376b63116b518d7a2a1eaf061be3d3752f85497d010000021c000000b02a45373256dae5ce1f24d34c51b90fa4d93fe18d48d979e40a0cb1434551e6bb60400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb660400eb6187ae98162350830e5333e41de8e10881566addbb3c43ffff6f01339654db1de1e6903670916fcbaa32e6ff004f1bae70159bf16e575fdf6a7f99d3caff9c37d000000b011995056113117cb5ec1544e69c660c360d83e3195e7012d8a50e3bc80022d3664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb664400eb630335117fdbcda57dd2004fa781cba03c532f2c87a8b37dabb163b468ffdf85a05bd1c8ac36d2eb7e2caf0f21cff0c0588f21bbb32838540283dcfb5eaaa09f8000000b02951b7ecacb8e9f256ae1b0703550a3f10a4831e5cadf9084e770bc9aab273b268400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb668400eb617876a3bb8130c551cbc85fc902a0b224ccb4f6cc798bf243b5a6dbfcaae3ed51d7584215ef500dedab7b7aab68db58138be60a7f94a7d1aec63f7c3155a50740000021c000000b010a5d110670f1bef964a9c091b625b5d983cdfc2a9bb8051cebb3e42e562ba2d6c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb66c400eb62f3fd1d2539ade7c14a94cb529b8b49dfc9794598e5fb6feff8095ccf55e855104c99d45194b32dc1a5438acce9b069fc056bd4c465804646ca82a3c500a96ef000000b0285e38a70296ee168e3762c1b4f104d9480924af7082782c92e16650101300a970400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb670400eb61693eaf60df110795445cdb741c605bc842ff0fddb6d3e487fc4c846300ecbcc1c8204dbb4d305031240ff656829b01b702302390d1efc3f30ce52497abadd6b000000b00fb251cabced2013cdd3e3c3ccfe55f7cfa18153bd8fff76132598c94ac3472474400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb674400eb62e4c528ca978e2a04c32946fdb54af3833fc35eaa234362343eaf0535abf124803d61dff6f29370051dd806780370139f7bb5edd5a2c8388b11284c2b56b23e600000fa400000168000000b0276ab9615874f23ac5c0aa7c668cff737f6dc6408456f750d74bc0d675738da078400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb678400eb615a06bb063cf149d8bcf1571f3620056bb94928eef41bd6cc42f22cc956f58c31b8e85960ab1092749ca472019c5aab5a787a3ca20f37b637538accfe01b6a62000000b00ebed28512cb2438055d2b7e7e9a5092070622e4d1647e9a578ff34fb023d41b7c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb67c400eb62d58d346ff56e6c483bbdc2a8cf0a9d26b60d77bb608b54788554ad9c01f9f3f02e29eb9c5073b248966c82231d2fbd42f20006e6e0102acf57cdf491acbb0dd00000168000000b026773a1bae52f65efd49f2371828fa0db6d267d1982b76751bb61b5cdad41a9780400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb680400eb614acec6ab9ad18c1c3585d2ca4fdfaf0f2f9342003163c9108997d52facfe5ba1a9b0650608f0d4b81538edacb61a54fdeec455b34c7fa87b9a30756457bf759000000b00dcb533f68a9285c3ce6733930364b2c3e6ac475e538fdbe9bfa4dd61584611284400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb684400eb62c6554015534eae8bb4523e53e8ca46ca2c5790cc9dd346bccbfa56025802c3601ef1f741ae53f48c0f00fdce36ef66e6684a1ff81d581d139e739cf802c3dd400000168000000b02583bad60430fa8334d339f1c9c4f4a7ee370962abfff599602075e34034a78e88400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb688400eb613b96d250f8b1ce5fae1a4e75699f58b2a5dd5b116eabbb54d03d7d9603072b119a7870ab66d116fb8dcd6957cfd9fea1650e6ec489c79abfe0d61dcaadc8450000000b00cd7d3f9be872c80746fbaf3e1d245c675cf6606f90d7ce2e064a85c7ae4ee098c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb68c400eb62b71d4bbab12ef0cf2ce6b9ff0289f06da2a1a9dddb1b3901129ffe68ae0b92d00fba02e70c3436cf8795797950af1089de9439095aa00f57e519455e58ccacb00000168000000b024903b905a0efea76c5c81ac7b60ef42259baaf3bfd474bda48ad069a595348590400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb690400eb612c5eddf6569210a326aeca20835f02561c277422abf3ad9916e325fc590ffa818b407c50c4b1593f0661e502e999a844db5887d5c70f8d04277bc63103d1147000000b00be454b4146530a4abf902ae936e4060ad3407980ce1fc0724cf02e2e0457b0094400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb694400eb62a7e557600f0f3312a57b35aa1c499a1118ebc2ef18632b455945a6cf0414624000820e8c6a1479130029f5246a6eba2d54de521a97e8019c2bbeedc4aed57c200000168000000b0239cbc4aafed02cba3e5c9672cfce9dc5d004c84d3a8f3e1e8f52af00af5c17c98400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb698400eb611d26e99bb47252e69f4345cb9d1eabf992718d33e93b9fdd5d88ce62af18c9f17c0887f622919b827ef660ae035951e851a2a0e704577f486e216e9759d9e3e000000b00af0d56e6a4334c8e3824a69450a3afae498a92920b67b2b69395d6945a607f79c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb69c400eb6298ad63056cef75561e0fb155360943b48f35dc0055ab1d899feb4f355a1d31b2f78f015fdb0ebdf1fdc2cc379c43e9a34e66efb370c6fcf4b083ef6a04de4ba00000168000000b022a93d0505cb06efdb6f1121de98e4769464ee15e77d73062d5f857670564e73a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb6a0400eb610deef5411252952a17d7c176b6de559d08bba64526839221a42e76c9052199616cd0939b8071ddc5f78adc591d18fb8bc7ecb9f8419f718cb4c716fdafe2b35000000b009fd5628c02138ed1b0b9223f6a635951bfd4aba348afa4fada3b7efab0694eea4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6a4400eb6289756eaacacfb79996a42d004fc8ed58057ff51192f30fcde690f79bb0260122e8570d0538ef0035765747e2b6039346c4b108c4ae0eef38f72997d05ae71b100000168000000b021b5bdbf5ba90b1412f858dc9034df10cbc98fa6fb51f22a71c9dffcd5b6db6aa8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb6a8400eb60feb700e67032d76d906c3d21d09dff407f05bf5663cb8465ead41f2f5b2a68d15d989f40de522009701f580436d8a52f3e36d3097ee763d0fb6cbf6405eb82c000000b00909d6e315ff3d115294d9dea842302f5361ec4b485f7973f20e1276106721e5ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb6ac400eb627a3d7a5028aff9dd0f38a8ab698896fb7bca0e22d03b02122d36a002062ed092d91f18aa96cf4278eeebc38dcfc33cea3afb21d5eb56e17d3dcf4036b0efea800000168000000b020c23e79b1870f384a81a09741d0d9ab032e31380f26714eb6343a833b176861b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb6b0400eb60ef7f0c8bce1319b10900b8ccea5da8e3f54fd867a11376aa3179c795b13338414e60aae63c32624ce8b3d3af50984ed2b480ec1abc2f5615421267ca5bf4523000000b00816579d6bdd41358a1e219959de2ac98ac68ddc5c33f89836786cfc75c7aedcb4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb6b4400eb626b0585f586903c2087cd24568348409ef21427340d82f45673dc48685c37a002c9e7244ff4af84bc67803f38e982e68db1453ae7289ed3c18474e89d06f8b9f00000168000000b01fcebf340765135c820ae851f36cd4453a92d2c922faf072fa9e9509a077f558b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb6b8400eb60e04718312bf35bf481953478041d52876b99f178de5b68ee781f6ffc073c07b13f28b68b9a12a49061484f5a6a57f8762acb052bf977485988b81030b1fd21a000000b00722d857c1bb4559c1a769540b7a2563c22b2f6d700877bc7ae2c782db283bd3bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb6bc400eb625bcd919ae4707e640061a0019d07ea42685e40454acae69aba81f0ceb2406f72baaf2ff5528fc6ffe014bae403429031278f53f865e6c605cb1a91035d0189600000168000000b01edb3fee5d431780b994300ca508cedf71f7745a36cf6f973f08ef9005d8824fc0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb6c0400eb60d10f23d689d39e37fa29b0231ddcfc2ae1e40a8a1ba35b32bec518625d44d7212ff0c230f7f2e6d3d9dccb058417a219a1151e3d36bf3a9dcf5db8970805f11000000b0062f59121799497df930b10ebd161ffdf98fd0fe83dcf6e0bf4d22094088c8cac4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb6c4400eb624c959d404250c0a778f61bacb6c793e5dea859568812d8df0127993508493ee2ab773b9ab070094358a9368f1d0239d49dd96d09a32eb84a11c03969b30a58d00000168000000b01de7c0a8b3211ba4f11d77c756a4c979a95c15eb4aa3eebb83734a166b390f46c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb6c8400eb60c1d72f7be7b3e07b72be2bce379ca5ce582e239b58eb4d77056ac0c8b34da69120b8cdd655d32917527146b09dd74bbd175f374e74072ce2160360fd5e0ec08000000b0053bd9cc6d774da230b9f8c96eb21a9830f4728f97b1760503b77c8fa5e955c1cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb6cc400eb623d5da8e5a03102eaf18a9757d0873d8954f27267c55acb2347cd419b5e520e529c3f47400e504b86d13db23a36c1e3781423861ae076aa8e5865e1d00913284380000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020100000000000000000000000000000000000000000000000000000000000002020000000000000000000000000000000000000000000000000000000000000203000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000000000000000000000000000000000000002050000000000000000000000000000000000000000000000000000000000000206000000000000000000000000000000000000000000000000000000000000020700000000000000000000000000000000000000000000000000000000000002080000000000000000000000000000000000000000000000000000000000000209000000000000000000000000000000000000000000000000000000000000020a000000000000000000000000000000000000000000000000000000000000020b000000000000000000000000000000000000000000000000000000000000020c000000000000000000000000000000000000000000000000000000000000020d000000000000000000000000000000000000000000000000000000000000020e000000000000000000000000000000000000000000000000000000000000020f0000000000000000000000000000000000000000000000000000000000000210000000000000000000000000000000000000000000000000000000000000021100000000000000000000000000000000000000000000000000000000000002120000000000000000000000000000000000000000000000000000000000000213000000000000000000000000000000000000000000000000000000000000021400000000000000000000000000000000000000000000000000000000000002150000000000000000000000000000000000000000000000000000000000000216000000000000000000000000000000000000000000000000000000000000021700000000000000000000000000000000000000000000000000000000000002180000000000000000000000000000000000000000000000000000000000000219000000000000000000000000000000000000000000000000000000000000021a000000000000000000000000000000000000000000000000000000000000021b000000000000000000000000000000000000000000000000000000000000021c000000000000000000000000000000000000000000000000000000000000021d000000000000000000000000000000000000000000000000000000000000021e000000000000000000000000000000000000000000000000000000000000021f0000000000000000000000000000000000000000000000000000000000000220000000000000000000000000000000000000000000000000000000000000022100000000000000000000000000000000000000000000000000000000000002220000000000000000000000000000000000000000000000000000000000000223000000000000000000000000000000000000000000000000000000000000022400000000000000000000000000000000000000000000000000000000000002250000000000000000000000000000000000000000000000000000000000000226000000000000000000000000000000000000000000000000000000000000022700000000000000000000000000000000000000000000000000000000000002280000000000000000000000000000000000000000000000000000000000000229000000000000000000000000000000000000000000000000000000000000022a000000000000000000000000000000000000000000000000000000000000022b000000000000000000000000000000000000000000000000000000000000022c000000000000000000000000000000000000000000000000000000000000022d000000000000000000000000000000000000000000000000000000000000022e000000000000000000000000000000000000000000000000000000000000022f00000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000000000231000000000000000000000000000000000000000000000000000000000000023200000000000000000000000000000000000000000000000000000000000002330000000000000000000000000000000000000000000000000000000000000234000000000000000000000000000000000000000000000000000000000000023500000000000000000000000000000000000000000000000000000000000002360000000000000000000000000000000000000000000000000000000000000237370000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000331000000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003330000000000000000000000000000000000000000000000000000000000000334000000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003360200000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000401100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000601000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000602000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000603000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000604000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000605000000000000000000000000000000000000000000000000000000000000060f00000000000000000000000000000000000000000000000000000000000006060000000000000000000000000000000000000000000000000000000000000610000000000000000000000000000000000000000000000000000000000000060700000000000000000000000000000000000000000000000000000000000006110000000000000000000000000000000000000000000000000000000000000608000000000000000000000000000000000000000000000000000000000000061200000000000000000000000000000000000000000000000000000000000006090000000000000000000000000000000000000000000000000000000000000613000000000000000000000000000000000000000000000000000000000000060a0000000000000000000000000000000000000000000000000000000000000614000000000000000000000000000000000000000000000000000000000000060b0000000000000000000000000000000000000000000000000000000000000615000000000000000000000000000000000000000000000000000000000000060c0000000000000000000000000000000000000000000000000000000000000616000000000000000000000000000000000000000000000000000000000000060d0000000000000000000000000000000000000000000000000000000000000617000000000000000000000000000000000000000000000000000000000000060e0000000000000000000000000000000000000000000000000000000000000618000000000000000000000000000000000000000000000000000000000000060f0000000000000000000000000000000000000000000000000000000000000619000011000000021c000000b01cf4416308ff1fc928a6bf820840c413e0c0b77c5e786ddfc7dda49cd0999c3dd0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb6d0400eb60b29f3b21459422beeb52a779515c4f71ce783cac96333fbb4c10692f095676011180d97bb3b36b5acb05c25bb796f5608da9505fb14f1f265ca90963b4178ff000000b004485a86c35551c668434084204e153268591420ab85f5294821d7160b49e2b8d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb6d4400eb622e25b48afe11452e6a1f1302ea46e72ccb3c8b7902a2bd678e72ea01b45addc28d0752e56c308dca49d22de550818d1b8a6d9f2c1dbe9cd29f0b8a365f1bf7b000000b01c00c21d5edd23ed6030073cb9dcbeae1825590d724ced040c47ff2335fa2934d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb6d8400eb60a36746c6a374650263e723246b1bf91544c255bdd37b31ff92b611955f5f45710248e5211193ad9e439a3e06d1569f0403f36970ee97116aa34eb1ca0a205f60000021c000000b00354db41193355ea9fcc883ed1ea0fcc9fbdb5b1bf5a744d8c8c319c70aa6fafdc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb6dc400eb621eedc0305bf18771e2b38eae040690d04186a48a3feaafabd51892680a63ad327dcf5e8aca10d00dc266a9906a4136bf00b7b83d5b068f16e5b1329cb524c72000000b01b0d42d7b4bb281197b94ef76b78b9484f89fa9e86216c2850b259a99b5ab62be0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb6e0400eb60942f526c0154a745dc7b9ecf84dba2b8bb0c6ecf10c32443d95bb9fbb56814e0f310f0c66f73efe1bc2eb9b1eb1648a77a3d82822bdf03aee9f45a3060292ed000000b002615bfb6f115a0ed755cff983860a66d7225742d32ef371d0f68c22d60afca6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb6e4400eb620fb5cbd5b9d1c9b55b480a591dc63a73b7d0bd9b7d32a1f01bbe3ace606c7ca26e976a3027f112513afb253b8400e0627701d14e984e815b2c56db030b2d9690000021c000000b01a19c3920a992c35cf4296b21d14b3e286ee9c2f99f5eb4c951cb43000bb4322e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6e8400eb6084f75e115f34e98955101a7a9e9b4c5c315687e04e0b1688200162620b70e450e3d8fc6bcd54322534c3355d04d5f24af0879b936926f5f3309a0296b631fe4000000b0016ddcb5c4ef5e330edf17b4352205010e86f8d3e70372961560e6a93b6b899dec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb6ec400eb62007dd77b17b20bf8d3dc86043785e4172e1ad6acba7a94346263e334b6754c125f5f75d585d15494b38fa0e69dc08a05ed4bea5fd596739f72fc83696136660000000b01926444c6077305a06cbde6cceb0ae7cbe533dc0adca6a70d9870eb6661bd019f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6f0400eb6075bf69b6bd152bcccda49625b85af5ffa7a0a0f18b5308cc66a70ac86179b3c0d4a108112b347468ad57b1081e959bee66d1b4a4a66ee837773faafd0c3acdb0000021c000000b0007a5d701acd625746685f6ee6bdff9b45eb9a64fad7f1ba59cb412fa0cc1694f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb6f4400eb61f145e32075924e3c4c7101af51458dbaa464efbdf7c28678a9098b9b0c7e1b825027817ae3b196d82c241c91b78033a96396037112de65e3b9a22bcfb73f357000000b01832c506b655347e3e552627804ca916f5b7df51c19ee9951df1693ccb7c5d10f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb6f8400eb606687755c1af56e10463911d0d21a9fa31deaba02c89afb10ad4cb32eb7828330c56913b68914b6ac25ec2cb338554591dd1bcdb5e3b6da7bbde5536362439d2000000b02feb2c9d51dd06a53641ece019db5292a584243e8865e16fe2179149f62ca38cfc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb6fc400eb61e20deec5d372907fc5057d5a6b05375e1aaf08cf350a78bcefaf34016286eaf240ef8d204191d91ba4b8983cd13fdd4cd9e01c82502658280047d4360d4804e0000021c000000b017a6cfd6dc3bc39624f9967152205e32c37c048c927b0904929824f9a605f73800410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb600410eb60574f810178d5b053becd8d7bebda49469434d31405e2ed54f3f25b950d8b52a0b6311f5be6f4f8ef9e80a85e5214ef355365e6c720feccc0048afbc9b84c6c9000000b02f5f376d77c395bd1ce65d29ebaf07ae73484979594200df56be4d06d0b63db404410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb604410eb61d94e9bc831db81fe2f4c81f78840891af6f15c7c42cc6fb43a1aefcf0b208d7238303a229ffaca9a0eff9cd9ee7b2f09b622702f5de84f1f4ab39003b5e1a76000000b016b350913219c7ba5c82de2c03bc58ccfae0a61da64f8828d7027f800b66842f08410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb608410eb604e902e03d73ea1d22914921909159b03707726c113a4e44c3e5e1762b624f520ad71cc5e455dea6e08c7acfb6f5040f22fa83a742ec0c3b74ef6b79760e60f10000021c000000b02e6bb827cda199e1546fa4e49d4b0248aaaceb0a6d1680039b28a78d3616caab0c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb60c410eb61ca16a76d8fbbc441a7e0fda2a20032be6d3b758d801461f880c0983561295ce228f845c7fddb0cdd87941885083ad8ad2c6c89409b3041639159386a0bea76d000000b015bfd14b87f7cbde940c25e6b5585367324547aeba24074d1b6cda0670c7112610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb610410eb603f5839a9351ee415a1a90dc422d544a6e6c13fd250ecd6908503bfc90c2dc4909e39d803a33e2cb1815c28a6890fea95a5f253856c08b5fb959c5ffdb6eede8000000b02d7838e2237f9e058bf8ec9f4ee6fce2e2118c9b80eaff27df9302139b7757a214410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb614410eb61badeb312ed9c06852075794dbbbfdc61e3858e9ebd5c543cc766409bb7322c5219c0516d5bbb4f210028943021fa8250a2b6a251d87833a7d7fee0d061f34640000021c000000b014cc5205ddd5d002cb956da166f44e0169a9e93fcdf886715fd7348cd6279e1d18410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb618410eb603020454e92ff26591a3d896f3c94ee4a5d0b58e38e34c8d4cba9682f623694008f01e3a9011e6ef4f9f0a451a2cf94391c3c6c96a950a83fdc4208640cf7adf000000b02c84b99c795da229c382345a0082f77d19762e2c94bf7e4c23fd5c9a00d7e4991c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61c410eb61aba6beb84b7c48c89909f4f8d57f860559cfa7affaa446810e0be9020d3afbc20a885d12b99b916478bd0fdb3bba2bf41900bb6315c025ec1ea48936b7fc15b000000b013d8d2c033b3d427031eb55c1890489ba10e8ad0e1cd0595a4418f133b882b1420410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb620410eb6020e850f3f0df689c92d2051a565497edd35571f4cb7cbb19124f1095b83f63707fc9ef4e5efeb13872851ffcbc8f3ddc928685a7e6989a8422e7b0ca63007d60000021c000000b02b913a56cf3ba64dfb0b7c14b21ef21750dacfbda893fd706867b7206638719024410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb624410eb619c6eca5da95c8b0c119e70a3ef3f2fa8d019c0c137ec38c554b191686343cb31fb5068b8177bd3a7f1518b865579d5978f4ad47453081830654a319d0e04e52000000b012e5537a8991d84b3aa7fd16ca2c4335d8732c61f5a184b9e8abe999a0e8b80b28410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb628410eb6011b05c994ebfaae00b6680c570144191499f8b0608c4ad5d58f4b8fc0e4832e07091faf3bcdef37beb199ba7d64ee78008d09eb923e08cc8698d5930b9094cd000000b02a9dbb112519aa723294c3cf63baecb1883f714ebc687c94acd211a6cb98fe872c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb62c410eb618d36d603073ccd4f8a32ec4f08fed94c4663d9d275342b099b5739ceb94c9aa1ec18745d755c15eb69e607316f397f3b0594ed8590500a74abefda03640db4900000fa400000168000000b011f1d434df6fdc6f723144d17bc83dd00fd7cdf3097603de2d1644200649450230410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb630410eb600278683eac9fed2383fafc7089d3eb34bfe9a417460c9fa19f9a616264510250615a06991abf35bf63ae1752f00e91237f1ab7ca61287f0cb03301970f121c4000000b029aa3bcb7af7ae966a1e0b8a1556e74bbfa412dfd03cfbb8f13c6c2d30f98b7e34410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb634410eb617dfee1a8651d0f9302c767fa22be82efbcadf2e3b27c1d4de1fce2350f556a11dce08002d33c582ee27a82dc88f928de7bdf0696cd97fcb8f2958269ba1684000000168000000b010fe54ef354de093a9ba8c8c2d64386a473c6f841d4a830271809ea66ba9d1f938410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb638410eb62f9855b121d9a32028193d383bba91aaab97241b01eeb9afa245f6307ba59d1d05222123e789f7802dc4292fe09ce3ac6f564d0db9e707150f6d8a9fd651aebb000000b028b6bc85d0d5b2baa1a75344c6f2e1e5f708b470e4117add35a6c6b3965a18753c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb63c410eb616ec6ed4dc2fd51d67b5be3a53c7e2c9332f80bf4efc40f9228a28a9b655e3981cda88ba8311c9a725b0efe87a2b8d281f2291fa80adfeefd393b2ad0101f53700000168000000b0100ad5a98b2be4b7e143d446df0033047ea11115311f0226b5eaf92cd10a5ef040410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb640410eb62ea4d66b77b7a7445fa284f2ed568c44e2fbc5ac15c338d3e6b050b6e1062a14042ea1de3d67fba4654d70ea9238de46a6baee9ecdbb863953d7e5263bb23bb2000000b027c33d4026b3b6ded9309aff788edc802e6d5601f7e5fa017a112139fbbaa56c44410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb644410eb615f8ef8f320dd9419f3f05f50563dd636a94225062d0c01d66f483301bb6708f1be70974d8efcdcb5d3a37a32bc787c25687338b94827e1417fe0d336662822e00000168000000b00f175663e109e8dc18cd1c01909c2d9eb605b2a644f3814afa5553b3366aebe748410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb648410eb62db15725cd95ab68972bccad9ef286df1a60673d2997b7f82b1aab3d4666b70b033b22989345ffc89cd6b8a543d4d8e0de1f902fe190055d98423faca112c8a9000000b026cfbdfa7c91bb0310b9e2ba2a2ad71a65d1f7930bba7925be7b7bc0611b32634c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb64c410eb61505704987ebdd65d6c84dafb6ffd7fda1f8c3e176a53f41ab5eddb68116fd861af38a2f2ecdd1ef94c37f5ddd63825c8debd51ca856fd385c6867b9cbc30f2500000168000000b00e23d71e36e7ed00505663bc42382838ed6a543758c8006f3ebfae399bcb78de50410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb650410eb62cbdd7e02373af8cceb51468508e817951c508ce3d6c371c6f8505c3abc744020247a352e92403ecd460005ff570d37b158431c0f5648481dcac9a33067355a0000000b025dc3eb4d26fbf2748432a74dbc6d1b49d3699241f8ef84a02e5d646c67bbf5a54410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb654410eb61411f103ddc9e18a0e51956a689bd297d95d65728a79be65efc9383ce6778a7d1a000ae984abd613cc4cc7188eff7cf6c55076adbc2b7c5ca0d2c24031239c1c00000168000000b00d3057d88cc5f12487dfab76f3d422d324cef5c86c9c7f93832a08c0012c05d558410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb658410eb62bca589a7951b3b1063e5c23022a7c138929aa5f5140b640b3ef604a1127d0f90154240d3f0208110be9481aa70cce154ce8d352093903a62116f4b96bd3e297000000b024e8bf6f284dc34b7fcc722f8d62cc4ed49b3ab53363776e475030cd2bdc4c515c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb65c410eb6131e71be33a7e5ae45dadd251a37cd3210c207039e4e3d8a343392c34bd81774190c8ba3da89da3803d60ed3409b7790fcb5183ecffffb80e53d1cc69684291300000168000000b00c3cd892e2a3f548bf68f331a5701d6d5c3397598070feb7c7946346668c92cc60410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb660410eb62ad6d954cf2fb7d53dc7a3ddb3c676adc08e4bf065153564f859bad076885df00060a4c794e00c3543728fd558a8c8af844d74e31d0d82ca65814f3fd1346f8e000000b023f540297e2bc76fb755b9ea3efec6e90bffdc464737f6928bba8b53913cd94864410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb664410eb6122af2788985e9d27d6424dfcbd3c7cc4826a894b222bcae789ded49b138a46b18190c5e3067de5c3b5f568df237722b3419b9cfe3d47aa529a7774cfbe4b60a00000168000000b00b49594d3881f96cf6f23aec570c1807939838ea94457ddc0bfebdcccbed1fc368410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb668410eb629e35a0f250dbbf97550eb9865627147f7f2ed8178e9b4893cc41556dbe8eae72fd173f4cbefb083334c1d468bc61ba6e3e5febcaa9b727fedcd9f5a2694fc86000000b02301c0e3d409cb93eedf01a4f09ac18343647dd75b0c75b6d024e5d9f69d663f6c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb66c410eb611377332df63edf6b4ed6c9a7d6fc2667f8b4a25c5f73bd2bd0847d01699316217258d188645e28072e89e48a3d36cc56b7e5b60f7a8f9c96e11d1d36145430100000168000000b00a55da078e5ffd912e7b82a708a812a1cafcda7ba819fd0050691853314dacba70410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb670410eb628efdac97aebc01dacda335316fe6be22f578f128cbe33ad812e6fdd414977de2eddf4af21cdb4a76ad565013d6216411b4aa04dbe6ff1a43237f9e08bf5897d000000b0220e419e29e7cfb82668495fa236bc1d7ac91f686ee0f4db148f40605bfdf33674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb674410eb61043f3ed3541f21aec76b4552f0bbd00b6efebb6d9cbbaf70172a2567bf9be5916320dd2dc23e6a4aa71e603556f675fa2e2fcf20b7d78edb27c2c59c6a5cff800000168000000b009625ac1e43e01b56604ca61ba440d3c02617c0cbbee7c2494d372d996ae39b178410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb678410eb627fc5b83d0c9c441e4637b0dc89a667c66bc30a3a092b2d1c598ca63a6aa04d52dea756977abb8cba25eacbbeefe10db52af41ded24470c876a25466f1561674000000b0211ac2587fc5d3dc5df1911a53d2b6b7b22dc0f982b573ff58f99ae6c15e802d7c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb67c410eb60f5074a78b1ff63f23fffc0fe0a7b79aee548d47eda03a1b45dcfcdce15a4b50153e8e8d3201eac8e1fb2dbe070b61f9da479e831f51f811f6e686e02c065cef00000168000000b0086edb7c3a1c05d99d8e121c6be007d639c61d9dcfc2fb48d93dcd5ffc0ec6a880410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb680410eb62708dc3e26a7c8661becc2c87a3661169e20d234b46731f60a0324ea0c0a91cc2cf6f623cd89bcefd9e7f476a09a0b758a13e36fe618efecbb0caeed56b6a36b000000b020274312d5a3d800957ad8d5056eb151e992628a9689f3239d63f56d26bf0d2484410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb684410eb60e5cf561e0fdfa635b8943ca9243b23525b92ed90174b93f8a47576346bad847144b0f4787dfeeed19847578b8a75c9411ac4014332677363b50e1669166e9e6", "txsEffectsHash": "0x53472a10e3068a8dcdc64c5d353bc5b93d293459f513c087e52471bc28094012", "decodedHeader": { "contentCommitment": { - "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "inHash": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", "outHash": "0xc2db86162c987f9328539ebf11947c30e3846f8bdb7a820aed2bbabd9544b9dc", "txTreeHeight": 2, "txsEffectsHash": "0x53472a10e3068a8dcdc64c5d353bc5b93d293459f513c087e52471bc28094012" @@ -95,8 +95,8 @@ } } }, - "header": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f00000001000000000000000000000000000000000000000000000000000000000000000253472a10e3068a8dcdc64c5d353bc5b93d293459f513c087e52471bc280940120000000000000000000000000000000000000000000000000000000000000000c2db86162c987f9328539ebf11947c30e3846f8bdb7a820aed2bbabd9544b9dc0a241c83a063083fad29b6c333afcd968f71f8a875544ff1f1f08cae7f770f510000001002c672a4d7bd90c4b6ba35bbc9906598862f626554be3cba05de19265a8ece71000001000ed22b14764d5756c4e97521b31e93e21192b98b3bc2e2559e07b1263ce7b1be000001801faf8e36b0fb8fb337acc1c32316e1fcbd0465d53c47a2dd73ebb031042566cb000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb615a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb", + "header": "0x012a86560737adb075e12af8253fb09abf17aa841fb56d180bc89f0d2d473c7f00000001000000000000000000000000000000000000000000000000000000000000000253472a10e3068a8dcdc64c5d353bc5b93d293459f513c087e52471bc28094012536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123cc2db86162c987f9328539ebf11947c30e3846f8bdb7a820aed2bbabd9544b9dc0a241c83a063083fad29b6c333afcd968f71f8a875544ff1f1f08cae7f770f510000001002c672a4d7bd90c4b6ba35bbc9906598862f626554be3cba05de19265a8ece71000001000ed22b14764d5756c4e97521b31e93e21192b98b3bc2e2559e07b1263ce7b1be000001801faf8e36b0fb8fb337acc1c32316e1fcbd0465d53c47a2dd73ebb031042566cb000000c00000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000a43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb615a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb", "l1ToL2MessagesHash": "0xb213c9c543fce2a66720d26a913fe0d018f72a47ccfe698baafcf4cced343cfd", - "publicInputsHash": "0x061b248db124a2a24b14c355dcfed82a9427fd0f021b4bbba4f94e1ba65b2206" + "publicInputsHash": "0x1b0a1c6994b2a08a07bc46473e2c220b886b9be4da98a4ee45fd37734c1c60db" } } \ 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 879684b3431..271ba99450e 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -52,12 +52,12 @@ ] }, "block": { - "archive": "0x15e0aec496ca08dc0f0f9f4ce1aac253632930835487ddbbb18c8bec39c616ab", + "archive": "0x1c4046feb368b147423eeb63abf02b5ef4b825e5374fac801af5389bf50604b5", "body": "0x0000001012e5643e26da426570dd999e0e044e5f83d60f3cd813c55059bc0ea0f4a7c9d413b2d2cea949fa0876265cd8eee3a4dce1e243783562ea07e2de537f469f7bf627abb3d4560e786bafd52f77ac52dea36c50419f32386567bd969b0c38e1bd7405d339cecb99fa74bfd631917f965357f0341d8c4dfe6a8f4b621d8df54c82941d560ac24523012499eeca2594f20ce238b7d21b98ad5c638767d70ee05532c2183e6d64e69b005709dfc4771c7ca5981adc54f3e8bd1b00222461ae90e44eda2f1d4572fe0b0b23100a7ea6d4780b25e826e41ca9e71897e010bcb218887b3d036d44eb30a430b5cfc6660270eb5fb7f274689ac73dfa53ba9d0739fe38637f01f7130af8c5888d4c65ea68109a1d58fe8d7d1ae62098857b0a3a3dcd393ef80ed8bcba6eb5e3b4887a32c51c5853b97a5eb59c87c520f36423c6d7be06071821ca1719330de5e3c51a521778b49cbbc1d53f8ed42e0562bf21ed72e8cb9a410b0e82ef5f7276df41353faef675fb408aeb246b6e2f704cab99bf28d1427e7b0fec7b9929c6effdcd045d3fdcec1d1b73faed495444699fab936630d69b519f0bf4f1453db36439419dbfba703b849d1aa5774fe9a5325e5bf3e7cdda9d1f7f2a9c2a035c72fd4a3e383306aff03448f9accc08a2c665837560cec8675fe2512bfaef35a8fb7df08a81001a7fd4903849c0371dedd87f31295f46269c5205dd00000004380000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000024100000000000000000000000000000000000000000000000000000000000002420000000000000000000000000000000000000000000000000000000000000243000000000000000000000000000000000000000000000000000000000000024400000000000000000000000000000000000000000000000000000000000002450000000000000000000000000000000000000000000000000000000000000246000000000000000000000000000000000000000000000000000000000000024700000000000000000000000000000000000000000000000000000000000002480000000000000000000000000000000000000000000000000000000000000249000000000000000000000000000000000000000000000000000000000000024a000000000000000000000000000000000000000000000000000000000000024b000000000000000000000000000000000000000000000000000000000000024c000000000000000000000000000000000000000000000000000000000000024d000000000000000000000000000000000000000000000000000000000000024e000000000000000000000000000000000000000000000000000000000000024f0000000000000000000000000000000000000000000000000000000000000250000000000000000000000000000000000000000000000000000000000000025100000000000000000000000000000000000000000000000000000000000002520000000000000000000000000000000000000000000000000000000000000253000000000000000000000000000000000000000000000000000000000000025400000000000000000000000000000000000000000000000000000000000002550000000000000000000000000000000000000000000000000000000000000256000000000000000000000000000000000000000000000000000000000000025700000000000000000000000000000000000000000000000000000000000002580000000000000000000000000000000000000000000000000000000000000259000000000000000000000000000000000000000000000000000000000000025a000000000000000000000000000000000000000000000000000000000000025b000000000000000000000000000000000000000000000000000000000000025c000000000000000000000000000000000000000000000000000000000000025d000000000000000000000000000000000000000000000000000000000000025e000000000000000000000000000000000000000000000000000000000000025f0000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000026100000000000000000000000000000000000000000000000000000000000002620000000000000000000000000000000000000000000000000000000000000263000000000000000000000000000000000000000000000000000000000000026400000000000000000000000000000000000000000000000000000000000002650000000000000000000000000000000000000000000000000000000000000266000000000000000000000000000000000000000000000000000000000000026700000000000000000000000000000000000000000000000000000000000002680000000000000000000000000000000000000000000000000000000000000269000000000000000000000000000000000000000000000000000000000000026a000000000000000000000000000000000000000000000000000000000000026b000000000000000000000000000000000000000000000000000000000000026c000000000000000000000000000000000000000000000000000000000000026d000000000000000000000000000000000000000000000000000000000000026e000000000000000000000000000000000000000000000000000000000000026f00000000000000000000000000000000000000000000000000000000000002700000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000027200000000000000000000000000000000000000000000000000000000000002730000000000000000000000000000000000000000000000000000000000000274000000000000000000000000000000000000000000000000000000000000027500000000000000000000000000000000000000000000000000000000000002760000000000000000000000000000000000000000000000000000000000000277370000000000000000000000000000000000000000000000000000000000000340000000000000000000000000000000000000000000000000000000000000034100000000000000000000000000000000000000000000000000000000000003420000000000000000000000000000000000000000000000000000000000000343000000000000000000000000000000000000000000000000000000000000034400000000000000000000000000000000000000000000000000000000000003450000000000000000000000000000000000000000000000000000000000000346000000000000000000000000000000000000000000000000000000000000034700000000000000000000000000000000000000000000000000000000000003480000000000000000000000000000000000000000000000000000000000000349000000000000000000000000000000000000000000000000000000000000034a000000000000000000000000000000000000000000000000000000000000034b000000000000000000000000000000000000000000000000000000000000034c000000000000000000000000000000000000000000000000000000000000034d000000000000000000000000000000000000000000000000000000000000034e000000000000000000000000000000000000000000000000000000000000034f0000000000000000000000000000000000000000000000000000000000000350000000000000000000000000000000000000000000000000000000000000035100000000000000000000000000000000000000000000000000000000000003520000000000000000000000000000000000000000000000000000000000000353000000000000000000000000000000000000000000000000000000000000035400000000000000000000000000000000000000000000000000000000000003550000000000000000000000000000000000000000000000000000000000000356000000000000000000000000000000000000000000000000000000000000035700000000000000000000000000000000000000000000000000000000000003580000000000000000000000000000000000000000000000000000000000000359000000000000000000000000000000000000000000000000000000000000035a000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035c000000000000000000000000000000000000000000000000000000000000035d000000000000000000000000000000000000000000000000000000000000035e000000000000000000000000000000000000000000000000000000000000035f0000000000000000000000000000000000000000000000000000000000000360000000000000000000000000000000000000000000000000000000000000036100000000000000000000000000000000000000000000000000000000000003620000000000000000000000000000000000000000000000000000000000000363000000000000000000000000000000000000000000000000000000000000036400000000000000000000000000000000000000000000000000000000000003650000000000000000000000000000000000000000000000000000000000000366000000000000000000000000000000000000000000000000000000000000036700000000000000000000000000000000000000000000000000000000000003680000000000000000000000000000000000000000000000000000000000000369000000000000000000000000000000000000000000000000000000000000036a000000000000000000000000000000000000000000000000000000000000036b000000000000000000000000000000000000000000000000000000000000036c000000000000000000000000000000000000000000000000000000000000036d000000000000000000000000000000000000000000000000000000000000036e000000000000000000000000000000000000000000000000000000000000036f00000000000000000000000000000000000000000000000000000000000003700000000000000000000000000000000000000000000000000000000000000371000000000000000000000000000000000000000000000000000000000000037200000000000000000000000000000000000000000000000000000000000003730000000000000000000000000000000000000000000000000000000000000374000000000000000000000000000000000000000000000000000000000000037500000000000000000000000000000000000000000000000000000000000003760200000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000000000441100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000641000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000642000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000643000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000644000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000645000000000000000000000000000000000000000000000000000000000000064f00000000000000000000000000000000000000000000000000000000000006460000000000000000000000000000000000000000000000000000000000000650000000000000000000000000000000000000000000000000000000000000064700000000000000000000000000000000000000000000000000000000000006510000000000000000000000000000000000000000000000000000000000000648000000000000000000000000000000000000000000000000000000000000065200000000000000000000000000000000000000000000000000000000000006490000000000000000000000000000000000000000000000000000000000000653000000000000000000000000000000000000000000000000000000000000064a0000000000000000000000000000000000000000000000000000000000000654000000000000000000000000000000000000000000000000000000000000064b0000000000000000000000000000000000000000000000000000000000000655000000000000000000000000000000000000000000000000000000000000064c0000000000000000000000000000000000000000000000000000000000000656000000000000000000000000000000000000000000000000000000000000064d0000000000000000000000000000000000000000000000000000000000000657000000000000000000000000000000000000000000000000000000000000064e0000000000000000000000000000000000000000000000000000000000000658000000000000000000000000000000000000000000000000000000000000064f0000000000000000000000000000000000000000000000000000000000000659000011000000021c000000b0077b5c368ffa09fdd51759d71d7c0270712abf2ee3977a6d1da827e6616f539f88410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb688410eb626155cf87c85cc8a53760a832bd25bb0d58573c5c83bb11a4e6d7f70716b1ec32c0376de2367c11411713c315236060fc1788500f9ed6f10ff770973bc173062000000b01f33c3cd2b81dc24cd04208fb70aabec20f7041baa5e7247e1ce4ff38c1f9a1b8c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb68c410eb60d69761c36dbfe8793128b8543dfaccf5d1dd06a15493863ceb1b1e9ac1b653e13579001ddbdf311510dbd336a43572e4910e1a546faf65a7fbb3becf6c776dd000000b00687dcf0e5d80e220ca0a191cf17fd0aa88f60bff76bf9916212826cc6cfe09690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb690410eb62521ddb2d263d0ae8aff523ddd6e564b0cea1556dc10303e92d7d9f6d6cbabba2b0ff7987945c53848fa83ec03d200a9f8dd26920dc1ee3543e163fa2177bd590000021c000000b01e404487815fe049048d684a68a6a686585ba5acbe32f16c2638aa79f180271294410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb694410eb60c75f6d68cba02abca9bd33ff57ba769948271fb291db788131c0c70117bf235126410bc339bf735889704ee1bdf51c8807583365acf757ec42596735c2803d4000000b005945dab3bb612464429e94c80b3f7a4dff402510b4078b5a67cdcf32c306d8d98410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb698410eb6242e5e6d2841d4d2c28899f88f0a50e5444eb6e7efe4af62d742347d3c2c38b12a1c7852cf23c95c8083cba6b56dfb443041c82321966d59884bbe8086d84a50000000b01d4cc541d73de46d3c16b0051a42a1208fc0473dd20770906aa3050056e0b4099c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb69c410eb60b827790e29806d002251afaa717a203cbe7138c3cf236ac578666f676dc7f2c117091768979fb59c0204ca8cd7b4c62b7da24c76ea3f4a3088ff0f9c18890cb0000021c000000b004a0de659194166a7bb33107324ff23f1758a3e21f14f7d9eae737799190fa84a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6a0410eb6233adf277e1fd8f6fa11e1b340a64b7f7bb3587903b92e871bac8f03a18cc5a82928f90d2501cd80b80d13616709f5de67a669b4356aec7dccb61906ec38d747000000b01c5945fc2d1be891739ff7bfcbde9bbac724e8cee5dbefb4af0d5f86bc414100a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb6a4410eb60a8ef84b38760af439ae62b558b39c9e034bb51d50c6b5d09bf0c17cdc3d0c23107d1230df57ff7df7a994637f1746fcef3ec658827873c74cfa4b8026e91dc2000000b003ad5f1fe7721a8eb33c78c1e3ebecd94ebd457332e976fe2f5191fff6f1877ba8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb6a8410eb622475fe1d3fddd1b319b296df2424619b317fa0a178dadab6016e98a06ed529f283579c77adfd1a4ef965b1c18a5f0789f0b0b45493f6ba21120738d5199643e0000021c000000b01b65c6b682f9ecb5ab293f7a7d7a9654fe898a5ff9b06ed8f377ba0d21a1cdf7ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6ac410eb6099b79058e540f187137aa700a4f97383ab056ae649b34f4e05b1c03419d991a0f8992eb353603a22f32dc1e30b3419726a367e9964cf2eb9164a6068c49aab9000000b002b9dfda3d501eb2eac5c07c9587e7738621e70446bdf62273bbec865c521472b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb6b0410eb62153e09c29dbe13f69247128a3de40b3ea7c9b9b2b622ccfa48144106c4ddf962741fa81d0bdd5c9271fa2d6ca41eb12d66facd65d13eac6558ace13b6f9f135000000b01a724770d8d7f0d9e2b287352f1690ef35ee2bf10d84edfd37e2149387025aeeb4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb6b4410eb608a7f9bfe432133ca8c0f22abbeb91d27214f83f786fb41924c57689a6fe26110e9613a58b1407c666bc23d8e24f3c315e08097aaa21720fd5cf008cf1aa37b00000021c000000b001c66094932e22d7224f08374723e20dbd8688955a927546b826470cc1b2a169b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6b8410eb6206061567fb9e563a0adb8e3557a3b4e21e13d2c3f36abf3e8eb9e96d1ae6c8d264e7b3c269bd9ed5ea8ea917bdde5ad0dd44e6770e869ea99f5289a1c5a7e2c000000b0197ec82b2eb5f4fe1a3bceefe0b28b896d52cd8221596d217c4c6f19ec62e7e5bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb6bc410eb607b47a7a3a101760e04a39e56d878c6ca97999d08c44333d692fd1100c5eb3080da2945fe0f20bea9e456b9393eb36cb956cab0bbdf5f1341a395b13570ac4a7000000b000d2e14ee90c26fb59d84ff1f8bfdca7f4eb2a266e66f46afc90a19327132e60c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb6c0410eb61f6ce210d597e987d837009e071635e85945debd530b2b182d55f91d370ef984255afbf67c79de119632324c2d79e0474538eff884bce90ede5f832081bb0b230000021c000000b0188b48e58493f92251c516aa924e8623a4b76f13352dec45c0b6c9a051c374dcc4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb6c4410eb606c0fb348fee1b8517d381a01f238706e0de3b61a018b261ad9a2b9671bf3fff0caf151a36d0100ed5ceb34e45873165ccd14c9cd1ca70585ea3b599bc6b519e000000b03043b07c201bcb4949b1dd632bdd2f9f5483b3fffbf4e42084dcf1ad7c73bb58c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb6c8410eb61e7962cb2b75edac0fc04858b8b2308290aa804e66dfaa3c71c053a39c6f867b24677cb0d257e235cdbb7a06df15dae17c9d91899891683322c9dda6e71b981a000000b01797c99fda71fd46894e5e6543ea80bddc1c10a449026b6a05212426b72401d3cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb6cc410eb605cd7beee5cc1fa94f5cc95ad0bf81a11842dcf2b3ed3185f204861cd71fccf60bbb95d48cae14330d57fb08f7232c000435ee2de59eef7ca30e102021cbde950000021c000000b02f50313675f9cf6d813b251ddd792a398be855910fc96344c9474c33e1d4484fd0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb6d0410eb61d85e3858153f1d0474990136a4e2b1cc80f21df7ab42960b62aae2a01d013722373fd6b2835e65a0544c1c190b1d57bb402331aac65e7576734382d4c7c2511000000b016a44a5a3050016ac0d7a61ff5867b581380b2355cd6ea8e498b7ead1c848ecad4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb6d4410eb604d9fca93baa23cd86e61115825b7c3b4fa77e83c7c1b0aa366ee0a33c8059ed0ac8168ee28c185744e142c3a8bf269a3b9a8fbef9736ea0e7786aa6872c6b8c000000b02e5cb1f0cbd7d391b8c46cd88f1524d3c34cf722239de2690db1a6ba4734d546d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb6d8410eb61c92643fd731f5f47ed2d7ce1bea25b6ff73c3708e88a884fa9508b06730a06922807e257e13ea7e3cce097c424dd015eb66d4abc03a667bab9e92b3b1dcb2080000021c000000b015b0cb14862e058ef860eddaa72275f24ae553c670ab69b28df5d93381e51bc1dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb6dc410eb603e67d63918827f1be6f58d033f776d5870c2014db962fce7ad93b29a1e0e6e409d49749386a1c7b7c6a8a7e5a5b213472ff31500d47edc52be2c52cec8cf883000000b02d6932ab21b5d7b5f04db49340b11f6dfab198b33772618d521c0140ac95623de0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb6e0410eb61b9ee4fa2d0ffa18b65c1f88cd86205136d86501a25d27a93eff6336cc912d60218cfedfd3f1eea274575136f3e9cab022cb763cd40ee59ff008ed3a173d3eff000000b014bd4bcedc0c09b32fea359558be708c8249f557847fe8d6d26033b9e745a8b8e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb6e4410eb602f2fe1de7662c15f5f8a08ae593716fbe70c1a5ef6aaef2bf4395b0074173db08e118038e48209fb3f3d2390bf71bceaa63d2e1211c6ce9704d1fb351ed857a00000fa400000168000000b02c75b3657793dbda27d6fc4df24d1a0832163a444b46e0b196865bc711f5ef34e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb6e8410eb61aab65b482edfe3cede567437f221aeb6e3d0692b631a6cd8369bdbd31f1ba5720997f9a29cff2c6abe098f1a585c54a5a3017cde7e364c4347347c07c9dcbf6000000b013c9cc8931ea0dd767737d500a5a6b26b9ae96e8985467fb16ca8e404ca635afec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb6ec410eb601ff7ed83d44303a2d81e845972f6c09f5d56337033f2e1703adf0366ca200d207ed98bde42624c3eb7d19f3bd931668e1c8747234f0ec0db4b77a39b74e127100000168000000b02b82341fcd71dffe5f604408a3e914a2697adbd55f1b5fd5daf0b64d77567c2bf0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb6f0410eb619b7e66ed8cc0261256eaefe30be1585a5a1a823ca0625f1c7d418439752474e1fa600547fadf6eae369e0ac5721bfe49194b95efbb7e3e878dda246e1fe58ed000000b012d64d4387c811fb9efcc50abbf665c0f1133879ac28e71f5b34e8c6b206c2a6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6f4410eb6010bff929322345e650b300048cb66a42d3a04c81713ad3b48184abcd2028dc906fa19783a0428e8230661ae6f2f1103192d160348c56b31f921d4c01cae9f6800000168000000b02a8eb4da234fe42296e98bc355850f3ca0df7d6672efdefa1f5b10d3dcb70922f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb6f8410eb618c467292eaa06855cf7f6b8e25a101fdd0649b4dddaa5160c3e72c9fcb2d4451eb2810ed58bfb0f1af3286708bdba7ec8f95af00f8c630cbd47fccd475ee5e4000000b011e2cdfddda6161fd6860cc56d92605b2877da0abffd66439f9f434d17674f9dfc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb6fc410eb60018804ce90038829c9477bafa67613e649ea6592ae82c5f8c82a54337631ac006069a328fe22d0c5a8fa96920cb0b9d5091b7945c99ea563d8c2f46820f2c5f00000168000000b02a02bfaa4936733a7d8dfc0d2758c4586ea3a2a143cbfe699401cc90b740a34a00420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb600420eb617d0e7e384880aa994813e7393f60aba146aeb45f1af243a50a8cd506213613c1dbf01c92b69ff33527c7021ba59b519005dfc812360e23101b25753acbf72db000000b01156d8ce038ca537bd2a7d0f3f661576f63bff4590d985b31445ff09f1f0e9c504420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb604420eb62ff0d98ff01867c43b892dbb4dbc6eb75a96b3dc757dbc60450b569401ecb4e9057aa502b5c8bc24413419b2f29ec0b91e55dccf2d7609c5b232eb035c98c68700000168000000b0290f40649f14775eb51743c7d8f4bef2a608443257a07d8dd86c27171ca1304108420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb608420eb61744f2b3aa6e99c17b25aebd65c9bfd5e22f1080c28b43a9c54f890d3c9cfb641d330c9951508e4b3920e06b8c2d6a34ce2221bbf43d01a07659131087490d03000000b010635988596aa95bf4b3c4c9f10210112da0a0d6a4ae04d758b05990575176bc0c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb60c420eb62efd5a4a45f66be873127575ff58695191fb556d89523b848975b11a674d41e0048725bd0ba6c04878bd616da43abb5355ba7e60414a88e9f69d4589c1f9537e00000168000000b0281bc11ef4f27b82eca08b828a90b98cdd6ce5c36b74fcb21cd6819d8201bd3810420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb610420eb61651736e004c9de5b2aef6781765ba701993b211d65fc2ce09b9e393a1fd885b1c3f8d53a72e926f70aa28263dc964cf0586c34d081180c4bac36d96eca999fa000000b00f6fda42af48ad802c3d0c84a29e0aab65054267b88283fb9d1ab416bcb203b314420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb614420eb62e09db049bd4700caa9bbd30b0f463ebc95ff6fe9d26baa8cde00ba0ccadced70393a6776184c46cb046a92855d6b5ed8d1f1ff1551f080e3b07a0102759e07500000168000000b0272841d94ad07fa72429d33d3c2cb42714d187547f497bd66140dc23e7624a2f18420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb618420eb6155df428562aa209ea383e32c901b50a50f853a2ea3441f24e243e1a075e15521b4c0e0dfd0c9693a8336fe0ef655f693ceb64de1be5ffe8ff2dc81d520a26f1000000b00e7c5afd0526b1a463c6543f543a05459c69e3f8cc57031fe1850e9d221290aa1c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb61c420eb62d165bbef1b27430e22504eb62905e8600c4988fb0fb39cd124a6627320e5bce02a02731b762c890e7cff0e30772b087c483c18268f387327f71fa968cba6d6c00000168000000b02634c293a0ae83cb5bb31af7edc8aec14c3628e5931dfafaa5ab36aa4cc2d72620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb620420eb6146a74e2ac08a62e21c185ed7a9dafa4885cf533fe08c116928e98a06cbea2491a588ec852ea9ab7dfbcb79ba1015a037450066f2fba7f0d439822a3b76ab3e8000000b00d88dbb75b04b5c89b4f9bfa05d5ffdfd3ce8589e02b824425ef692387731da124420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb624420eb62c22dc794790785519ae4ca6142c592038293a20c4cfb8f156b4c0ad976ee8c501aca7ec0d40ccb51f59389db90eab21fbe863137cc80656c3dc551cf21afa6300000168000000b02541434df68c87ef933c62b29f64a95b839aca76a6f27a1eea159130b223641d28420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb628420eb61376f59d01e6aa52594acda82c39aa3ebfc196c511dd403ad6f8f326d21f2f4019650f82a8c89edc1745ff56529d549dabb4a800438efe3188027d2a1ccb40df000000b00c955c71b0e2b9ecd2d8e3b4b771fa7a0b33271af40001686a59c3a9ecd3aa982c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62c420eb62b2f5d339d6e7c7951379460c5c853ba6f8ddbb1d8a438159b1f1b33fccf75bc00b928a6631ed0d956e280586aaaa5bc334d04a4909c857b0846afa3577b875a00000168000000b0244dc4084c6a8c13cac5aa6d5100a3f5baff6c07bac6f9432e7febb71783f11430420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb630420eb61283765757c4ae7690d41562ddd5a4d8f726385625b1bf5f1b634dad377fbc371871903cfea6a3004ecf471104394f37e319499157637d55cc6cd7b0822bcdd6000000b00ba1dd2c06c0be110a622b6f690df5144297c8ac07d4808caec41e305234378f34420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb634420eb62a3bddedf34c809d88c0dc1b77644e54a6f27d42ec78b739df8975ba623002b33029f7d39a2e752746bc0dc99dc7f8b392e58e7e1e2a75309092ffbdacdc145200000168000000b0235a44c2a2489038024ef228029c9e8ff2640d98ce9b786772ea463d7ce47e0b38420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb638420eb6118ff711ada2b29ac85d5d1d8f719f732e8ad9e739863e835fcda8339ce0492e177e10f75484a72486588ecbb5d549d21a7deb226b37fc7a10d73236e78c5acd000000b00aae5de65c9ec23541eb732a1aa9efae79fc6a3d1ba8ffb0f32e78b6b794c4863c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb63c420eb629485ea8492a84c1c04a23d6290048eede571ed4004d365e23f3d040c7908faa2f36788df00c794b7e4555844f63f34dca4a300f31fef454d4fd5a44123ca149380000000000000000000000000000000000000000000000000000000000000280000000000000000000000000000000000000000000000000000000000000028100000000000000000000000000000000000000000000000000000000000002820000000000000000000000000000000000000000000000000000000000000283000000000000000000000000000000000000000000000000000000000000028400000000000000000000000000000000000000000000000000000000000002850000000000000000000000000000000000000000000000000000000000000286000000000000000000000000000000000000000000000000000000000000028700000000000000000000000000000000000000000000000000000000000002880000000000000000000000000000000000000000000000000000000000000289000000000000000000000000000000000000000000000000000000000000028a000000000000000000000000000000000000000000000000000000000000028b000000000000000000000000000000000000000000000000000000000000028c000000000000000000000000000000000000000000000000000000000000028d000000000000000000000000000000000000000000000000000000000000028e000000000000000000000000000000000000000000000000000000000000028f0000000000000000000000000000000000000000000000000000000000000290000000000000000000000000000000000000000000000000000000000000029100000000000000000000000000000000000000000000000000000000000002920000000000000000000000000000000000000000000000000000000000000293000000000000000000000000000000000000000000000000000000000000029400000000000000000000000000000000000000000000000000000000000002950000000000000000000000000000000000000000000000000000000000000296000000000000000000000000000000000000000000000000000000000000029700000000000000000000000000000000000000000000000000000000000002980000000000000000000000000000000000000000000000000000000000000299000000000000000000000000000000000000000000000000000000000000029a000000000000000000000000000000000000000000000000000000000000029b000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000029d000000000000000000000000000000000000000000000000000000000000029e000000000000000000000000000000000000000000000000000000000000029f00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002a100000000000000000000000000000000000000000000000000000000000002a200000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000000000000000002a400000000000000000000000000000000000000000000000000000000000002a500000000000000000000000000000000000000000000000000000000000002a600000000000000000000000000000000000000000000000000000000000002a700000000000000000000000000000000000000000000000000000000000002a800000000000000000000000000000000000000000000000000000000000002a900000000000000000000000000000000000000000000000000000000000002aa00000000000000000000000000000000000000000000000000000000000002ab00000000000000000000000000000000000000000000000000000000000002ac00000000000000000000000000000000000000000000000000000000000002ad00000000000000000000000000000000000000000000000000000000000002ae00000000000000000000000000000000000000000000000000000000000002af00000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000002b100000000000000000000000000000000000000000000000000000000000002b200000000000000000000000000000000000000000000000000000000000002b300000000000000000000000000000000000000000000000000000000000002b400000000000000000000000000000000000000000000000000000000000002b500000000000000000000000000000000000000000000000000000000000002b600000000000000000000000000000000000000000000000000000000000002b7370000000000000000000000000000000000000000000000000000000000000380000000000000000000000000000000000000000000000000000000000000038100000000000000000000000000000000000000000000000000000000000003820000000000000000000000000000000000000000000000000000000000000383000000000000000000000000000000000000000000000000000000000000038400000000000000000000000000000000000000000000000000000000000003850000000000000000000000000000000000000000000000000000000000000386000000000000000000000000000000000000000000000000000000000000038700000000000000000000000000000000000000000000000000000000000003880000000000000000000000000000000000000000000000000000000000000389000000000000000000000000000000000000000000000000000000000000038a000000000000000000000000000000000000000000000000000000000000038b000000000000000000000000000000000000000000000000000000000000038c000000000000000000000000000000000000000000000000000000000000038d000000000000000000000000000000000000000000000000000000000000038e000000000000000000000000000000000000000000000000000000000000038f0000000000000000000000000000000000000000000000000000000000000390000000000000000000000000000000000000000000000000000000000000039100000000000000000000000000000000000000000000000000000000000003920000000000000000000000000000000000000000000000000000000000000393000000000000000000000000000000000000000000000000000000000000039400000000000000000000000000000000000000000000000000000000000003950000000000000000000000000000000000000000000000000000000000000396000000000000000000000000000000000000000000000000000000000000039700000000000000000000000000000000000000000000000000000000000003980000000000000000000000000000000000000000000000000000000000000399000000000000000000000000000000000000000000000000000000000000039a000000000000000000000000000000000000000000000000000000000000039b000000000000000000000000000000000000000000000000000000000000039c000000000000000000000000000000000000000000000000000000000000039d000000000000000000000000000000000000000000000000000000000000039e000000000000000000000000000000000000000000000000000000000000039f00000000000000000000000000000000000000000000000000000000000003a000000000000000000000000000000000000000000000000000000000000003a100000000000000000000000000000000000000000000000000000000000003a200000000000000000000000000000000000000000000000000000000000003a300000000000000000000000000000000000000000000000000000000000003a400000000000000000000000000000000000000000000000000000000000003a500000000000000000000000000000000000000000000000000000000000003a600000000000000000000000000000000000000000000000000000000000003a700000000000000000000000000000000000000000000000000000000000003a800000000000000000000000000000000000000000000000000000000000003a900000000000000000000000000000000000000000000000000000000000003aa00000000000000000000000000000000000000000000000000000000000003ab00000000000000000000000000000000000000000000000000000000000003ac00000000000000000000000000000000000000000000000000000000000003ad00000000000000000000000000000000000000000000000000000000000003ae00000000000000000000000000000000000000000000000000000000000003af00000000000000000000000000000000000000000000000000000000000003b000000000000000000000000000000000000000000000000000000000000003b100000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000000003b300000000000000000000000000000000000000000000000000000000000003b400000000000000000000000000000000000000000000000000000000000003b500000000000000000000000000000000000000000000000000000000000003b60200000000000000000000000000000000000000000000000000000000000004800000000000000000000000000000000000000000000000000000000000000481100000000000000000000000000000000000000000000000000000000000000680000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000681000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000682000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000683000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000684000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000685000000000000000000000000000000000000000000000000000000000000068f00000000000000000000000000000000000000000000000000000000000006860000000000000000000000000000000000000000000000000000000000000690000000000000000000000000000000000000000000000000000000000000068700000000000000000000000000000000000000000000000000000000000006910000000000000000000000000000000000000000000000000000000000000688000000000000000000000000000000000000000000000000000000000000069200000000000000000000000000000000000000000000000000000000000006890000000000000000000000000000000000000000000000000000000000000693000000000000000000000000000000000000000000000000000000000000068a0000000000000000000000000000000000000000000000000000000000000694000000000000000000000000000000000000000000000000000000000000068b0000000000000000000000000000000000000000000000000000000000000695000000000000000000000000000000000000000000000000000000000000068c0000000000000000000000000000000000000000000000000000000000000696000000000000000000000000000000000000000000000000000000000000068d0000000000000000000000000000000000000000000000000000000000000697000000000000000000000000000000000000000000000000000000000000068e0000000000000000000000000000000000000000000000000000000000000698000000000000000000000000000000000000000000000000000000000000068f0000000000000000000000000000000000000000000000000000000000000699000011000000021c000000b02266c57cf826945c39d839e2b438992a29c8af29e26ff78bb754a0c3e2450b0240420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb640420eb6109c77cc0380b6beffe6a4d8410d9a0d65ef7b784d5abda7a43802ba0240d625168a91b1aa62ab48bde1d6866771446c51e28cb37f0c7b9e55418cbd4cece7c4000000b009badea0b27cc6597974bae4cc45ea48b1610bce2f7d7ed53798d33d1cf5517d44420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb644420eb62854df629f0888e5f7d36b90da9c438915bbc0651421b582685e2ac72cf11ca12e42f94845ea7d6fb5ce9d3f00ffede801aed1a045d373791967b4ca779d2e40000000b0217346374e0498807161819d65d493c4612d50baf64476affbbefb4a47a597f948420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb648420eb60fa8f886595ebae3376fec92f2a994a79d541d09612f3ccbe8a25d4067a1631c1597126c0040af6cf56b1e41190d3f0689472e4492e0fac299abe743b24d74bb0000021c000000b008c75f5b085aca7db0fe029f7de1e4e2e8c5ad5f4351fdf97c032dc38255de744c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb64c420eb62761601cf4e68d0a2f5cb34b8c383e234d2061f627f634a6acc8854d9251a9982d4f7a029bc88193ed57e4f9b29be8823913733159a7f29d5dd20f50dcfdbb37000000b0207fc6f1a3e29ca4a8eac95817708e5e9891f24c0a18f5d4402955d0ad0624f050420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb650420eb60eb57940af3cbf076ef9344da4458f41d4b8be9a7503bbf02d0cb7c6cd01f01314a39326561eb3912cf465fbcaa939a0c0abcfd5a6b579e6de1641ca17ae01b2000000b007d3e0155e38cea1e8874a5a2f7ddf7d202a4ef057267d1dc06d8849e7b66b6b54420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb654420eb6266de0d74ac4912e66e5fb063dd438bd848503873bcab3caf132dfd3f7b2368f2c5bfabcf1a685b824e12cb46437e31c707814c26d7c71c1a23c69d7425e482e0000021c000000b01f8c47abf9c0a0c8e0741112c90c88f8cff693dd1ded74f88493b0571266b1e758420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb658420eb60dc1f9fb051ac32ba6827c0855e189dc0c1d602b88d83b147177124d32627d0a13b013e0abfcb7b5647dadb67c45343af8107166ba89f90b22809c507d0e8ea9000000b006e060cfb416d2c620109214e119da17578ef0816afafc4204d7e2d04d16f8625c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb65c420eb6257a6191a0a295529e6f42c0ef703357bbe9a5184f9f32ef359d3a5a5d12c3862b687b77478489dc5c6a746f15d3ddb6a7dcb6538150f0e5e6a6c45da7bed525000000b01e98c8664f9ea4ed17fd58cd7aa88393075b356e31c1f41cc8fe0add77c73ede60420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb660420eb60cce7ab55af8c74fde0bc3c3077d8476438201bc9cacba38b5e16cd397c30a0112bc949b01dabbd99c06f5712de12ed52f7512f7ce5e782f66eaf6d6e26f1ba00000021c000000b005ece18a09f4d6ea5799d9cf92b5d4b18ef392127ecf7b6649423d56b277855964420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb664420eb62486e24bf6809976d5f88a7ba10c2df1f34e46a96373b2137a0794e0c273507d2a74fc319d628e0093f3bc29c76fd850df4157e49525700a2b111ee40d1f621c000000b01da54920a57ca9114f86a0882c447e2d3ebfd6ff459673410d686563dd27cbd568420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb668420eb60bdafb6fb0d6cb7415950b7db9197f107ae6a34db081395cfa4bc759fd2396f811c9155557b8bffdd3903d2bdf7d296f66d9b488e232f753ab55515d47cfa897000000b004f962445fd2db0e8f23218a4451cf4bc65833a392a3fa8a8dac97dd17d812506c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb66c420eb6239363064c5e9d9b0d81d23652a8288c2ab2e83a77483137be71ef6727d3dd7429817cebf3409224cb7d03e4790bd2eb16a5f975a8f9ef2e6f7b796a727fef130000021c000000b01cb1c9dafb5aad35870fe842dde078c776247890596af26551d2bfea428858cc70420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb670420eb60ae77c2a06b4cf984d1e53386ab579aab24b44dec455b8813eb621e0628423ef10d5960fad96c4220b1984e6911924099e3e5619f6077677efbfabe3ad30358e000000b00405e2feb5b0df32c6ac6944f5edc9e5fdbcd534a67879aed216f2637d389f4774420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb674420eb6229fe3c0a23ca1bf450b19f104442326621789cb8b1cb05c02dc49ed8d346a6b288dfda6491e964903064b9f2aa7cd854e0a9b06bcce6e52b3e5d3f0d7e07c0a000000b01bbe4a955138b159be992ffd8f7c7361ad891a216d3f7189963d1a70a7e8e5c378420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb678420eb609f3fce45c92d3bc84a79af31c517444e9afe66fd82a37a583207c66c7e4b0e60fe216ca0374c84642a2cca142b51ea3d5a2f7ab09dbf59c342a066a1290c2850000021c000000b0031263b90b8ee356fe35b0ffa789c480352176c5ba4cf8d316814ce9e2992c3e7c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb67c420eb621ac647af81aa5e37c9461abb5e01dc0997c2b5c9ef12f804746a473f294f762279a7e609efc9a6d3a8f9359dc43c81f856f3c97d0a2ed76f8502e773d410901000000b01acacb4fa716b57df62277b841186dfbe4edbbb28113f0addaa774f70d4972ba80420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb680420eb609007d9eb270d7e0bc30e2adcded6edf21148800ebfeb6c9c78ad6ed2d453ddd0eee97845952cc6a7a2c145bf451193e0d07993c1db074c0789460f077f14f7c000000b0021ee473616ce77b35bef8ba5925bf1a6c861856ce2177f75aeba77047f9b93584420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb684420eb620b8e5354df8aa07b41da966677c185ad0e0ccedb2c5aea48bb0fefa57f5845926a6ff1af4da9e917218db148ddfc2b9bcd3de28e4776c9b3cba88fda2a195f80000021c000000b019d74c09fcf4b9a22dabbf72f2b468961c525d4394e86fd21f11cf7d72a9ffb188420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb688420eb6080cfe59084edc04f3ba2a687f89697958792991ffd335ee0bf5317392a5cad40dfb183eaf30d08eb1b55c16a5ed13d8446c3acd3184f3e4bcfebb76dd51dc73000000b0012b652db74aeb9f6d4840750ac1b9b4a3eab9e7e1f5f71b9f5601f6ad5a462c8c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb68c420eb61fc565efa3d6ae2beba6f121191812f508456e7ec69a2dc8d01b5980bd56115025b37fd54ab8a2b5a9a222cf3f7bbd53f4387fb9f84bebbf8124e384080222ef000000b018e3ccc452d2bdc66535072da450633053b6fed4a8bceef6637c2a03d80a8ca890420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb690420eb607197f135e2ce0292b437223312564138fddcb2313a7b512505f8bf9f80657cb0d0798f9050ed4b2e93ea3d157890e727bd0dc5e45597309016915fd42b2696a0000021c000000b00037e5e80d28efc3a4d1882fbc5db44edb4f5b78f5ca763fe3c05c7d12bad32394420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb694420eb61ed1e6a9f9b4b250233038dbcab40d8f3faa100fda6eaced1485b40722b69e4724c0008fa096a6d9e12b6a89f117b7ee2b9d214b0c206ae3c58f3e0a6d62afe6000000b017f04d7ea8b0c1ea9cbe4ee855ec5dca8b1ba065bc916e1aa7e6848a3d6b199f98420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb698420eb60625ffcdb40ae44d62ccb9dde2c15eadc7426cb4277c343694c9e6805d66e4c20c1419b35aecd8d720c7eb8c0925090cb3357def592df22d45d37083a812f661000000b02fa8b5154438941194ab15a0ef7b07463ae7e552835865f56c0cac97681b601b9c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb69c420eb61dde67644f92b6745ab980967c500829770eb1a0ee432c1158f00e8d88172b3e23cc8149f674aafe18b4b244a2b3b2886301c2dc1ff4ea0809f99890d2c33cdd00000fa400000168000000b016fcce38fe8ec60ed44796a307885864c28041f6d065ed3eec50df10a2cba696a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb6a0420eb60532808809e8e8719a560198945d5947fea70e453b50b35ad9344106c2c771b90b209a6db0cadcfb58513346bac103a6ea9a1f806d0271518a3dcb0a0d738358000000b02eb535cf9a169835cc345d5ba11701e0724c86e3972ce519b077071dcd7bed12a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb6a4420eb61ceae81ea570ba989242c8512dec02c3ae7353320217ab359d5a6913ed77b83522d902044c52af22503df9ff544fad229a66646d33c9692c4e63f3173823c9d400000168000000b016094ef3546cca330bd0de5db92452fef9e4e387e43a6c6330bb3997082c338da8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6a8420eb6043f01425fc6ec95d1df495345f953e2360bafd64f25327f1d9e9b8d2827feb00a2d1b2806a8e11f8fda7b016c5cfe4121fec11180d6f075cea8259072d4104f000000b02dc1b689eff49c5a03bda51652b2fc7aa9b12874ab01643df4e161a432dc7a09ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb6ac420eb61bf768d8fb4ebebcc9cc100bdf87fd5de5d7f4c315ec2a59e1c4c39a52d8452c21e582bea230b34687c741ba05eba7bcd1cb05fe479de85092ce4d9d9d8456cb00000168000000b01515cfadaa4ace57435a26186ac04d9931498518f80eeb877525941d6d8cc084b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6b0420eb6034b81fcb5a4f0ba0968910df7954e7c6d70516762f9b1a36208f6138d888ba709399be25c86e543c763c2bc1df8f8db596362a294ab6f9a13128016d8349d46000000b02cce374445d2a07e3b46ecd1044ef714e115ca05bed5e362394bbc2a983d0700b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb6b4420eb61b03e993512cc2e1015557c69123f7f81d3c965429c0a97e262f1e20b838d22320f20378f80eb76abf508974b787a257092fa78f5b726774d738a82402e4e3c200000168000000b0142250680028d27b7ae36dd31c5c483368ae26aa0be36aabb98feea3d2ed4d7bb8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6b8420eb6025802b70b82f4de40f1d8c8a9314916a4d4f2f876ce30c7a6735099f2e9189e08461c9cb264e967feed0a76cf94f37590c80433a87feebe577cda9d3d952a3d000000b02bdab7fe9bb0a4a272d0348bb5eaf1af187a6b96d2aa62867db616b0fd9d93f7bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb6bc420eb61a106a4da70ac70538de9f8142bff29254a137e53d9528a26a9978a71d995f1a1ffe84334decbb8ef6d9d12f69239cf1409449206f46e6991ba302aa684570b900000168000000b0132ed1225606d69fb26cb58dcdf842cda012c83b1fb7e9cffdfa492a384dda72c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6c0420eb6016483716160f902787b20835acd43b0dc3994898aa2afebeaddab205849a59507529d570842ed8c367652318130ee0fc82ca5c4bc546de29be73523a2f5b734000000b02ae738b8f18ea8c6aa597c466786ec494fdf0d27e67ee1aac220713762fe20eec4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6c4420eb6191ceb07fce8cb297067e73bf45bed2c8c05d9765169a7c6af03d32d82f9ec111f0b04eda3cabfb32e6318ea1abf978b77f8eab1831b65bd600d5d30cda5fdb000000168000000b0123b51dcabe4dac3e9f5fd487f943d67d77769cc338c68f44264a3b09dae6769c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb6c8420eb60071042bb73efd26b004683e0c693e4b139e361a9e772f102f4805a6bdaa328c065f1e115e20f1b06dff99ec32cce8a9ff914755d028ed06e0518faa0856442b000000b029f3b973476caceae1e2c4011922e6e38743aeb8fa5360cf068acbbdc85eade5cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb6cc420eb618296bc252c6cf4da7f12ef6a5f7e7c6c36a7b07653e26eaf36e2db3e85a79081e1785a7f9a8c3d765ec60a4cc5b9225af5d8c4296efe4e1a477b7b733068aa700000168000000b01147d29701c2dee8217f4503313038020edc0b5d4760e81886cefe37030ef460d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb6d0420eb62fe1d358ee4ea1749fddf5af3f8691427336bff42c051ec5b79455c1130abf84056b9ecbb3fef5d4a588e1a6e468e34436f5e8e6e3fd6c2b24bbea306db6d122000000b029003a2d9d4ab10f196c0bbbcabee17dbea8504a0e27dff34af526442dbf3adcd4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb6d4420eb61735ec7ca8a4d371df7a76b15793e260facf1c987912a60f37d8883a4dbb05ff1d2406624f86c7fb9d75a85f7df78cbfe6c22dd3aac46405e8e2123d9867179e00000168000000b01054535157a0e30c59088cbde2cc329c4640acee5b35673ccb3958bd686f8157d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb6d8420eb62eee5413442ca598d7673d69f1228bdcaa9b61853fd99de9fbfeb047786b4c7b04781f8609dcf9f8dd1229619604ddde6e5a8a77f7d1eb4f692644b6d3175e19000000b0280cbae7f328b53350f553767c5adc17f60cf1db21fc5f178f5f80ca931fc7d3dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb6dc420eb616426d36fe82d7961703be6c092fdcfb3233be298ce725337c42e2c0b31b92f61c30871ca564cc1fd4fef01a2f93875a1e26cf64be98e32a2d4c6cc3fdc7a49500000168000000b00f60d40bad7ee7309091d47894682d367da54e7f6f09e6610fa3b343cdd00e4ee0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb6e0420eb62dfad4cd9a0aa9bd0ef08524a2be8676e200031653ae1d0e40690acdddcbd9720384a0405fbafe1d149b711c47a0d878a5bf2c090ba66a73ad909f3d3877eb10000000b027193ba24906b957887e9b312df6d6b22d71936c35d0de3bd3c9db50f88054cae4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6e4420eb6154eedf15460dbba4e8d0626bacbd79569985fbaa0bba457c0ad3d47187c1fed1b3d07d6fb42d0440c8837d4e12f81f4558b70f5d26d624e71b6c74a6328318c00000168000000b00e6d54c6035ceb54c81b1c33460427d0b509f01082de6585540e0dca33309b45e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb6e8420eb62d075587efe8ade14679ccdf545a81111964a4a767829c3284d36554432c6669029120fab59902414c24b8d6f93cd312dd23cd9a1f7ae997f1faf9c39dd87807000000b02625bc5c9ee4bd7bc007e2ebdf92d14c64d634fd49a55d60183435d75de0e1c1ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6ec420eb6145b6eabaa3edfde86164de16c67d22fa0fd014bb490237c051797cd7ddcace41a4988915120d46844117f8f92cb7c8e8cf01286e641e172b62121d0c888be8300000168000000b00d79d580593aef78ffa463edf7a0226aec6e91a196b2e4a9987868509891283cf0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb6f0420eb62c13d64245c6b2057e03149a05f67bab50c946387b571b56c93dbfdaa88cf360019da1b50b77066583ae0091aad8cdad14886f2b334f68bc3665544a033904fe000000b025323d16f4c2c19ff7912aa6912ecbe69c3ad68e5d79dc845c9e905dc3416eb8f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb6f4420eb61367ef66001ce402bd9f959c1e03ccc9d861a2dcc864a2a04981f253e33d39db1956094ba6fed88c7b9ac74a44677728c454b417fa166096fa8b7c572de94b7a3800000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002c100000000000000000000000000000000000000000000000000000000000002c200000000000000000000000000000000000000000000000000000000000002c300000000000000000000000000000000000000000000000000000000000002c400000000000000000000000000000000000000000000000000000000000002c500000000000000000000000000000000000000000000000000000000000002c600000000000000000000000000000000000000000000000000000000000002c700000000000000000000000000000000000000000000000000000000000002c800000000000000000000000000000000000000000000000000000000000002c900000000000000000000000000000000000000000000000000000000000002ca00000000000000000000000000000000000000000000000000000000000002cb00000000000000000000000000000000000000000000000000000000000002cc00000000000000000000000000000000000000000000000000000000000002cd00000000000000000000000000000000000000000000000000000000000002ce00000000000000000000000000000000000000000000000000000000000002cf00000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000002d100000000000000000000000000000000000000000000000000000000000002d200000000000000000000000000000000000000000000000000000000000002d300000000000000000000000000000000000000000000000000000000000002d400000000000000000000000000000000000000000000000000000000000002d500000000000000000000000000000000000000000000000000000000000002d600000000000000000000000000000000000000000000000000000000000002d700000000000000000000000000000000000000000000000000000000000002d800000000000000000000000000000000000000000000000000000000000002d900000000000000000000000000000000000000000000000000000000000002da00000000000000000000000000000000000000000000000000000000000002db00000000000000000000000000000000000000000000000000000000000002dc00000000000000000000000000000000000000000000000000000000000002dd00000000000000000000000000000000000000000000000000000000000002de00000000000000000000000000000000000000000000000000000000000002df00000000000000000000000000000000000000000000000000000000000002e000000000000000000000000000000000000000000000000000000000000002e100000000000000000000000000000000000000000000000000000000000002e200000000000000000000000000000000000000000000000000000000000002e300000000000000000000000000000000000000000000000000000000000002e400000000000000000000000000000000000000000000000000000000000002e500000000000000000000000000000000000000000000000000000000000002e600000000000000000000000000000000000000000000000000000000000002e700000000000000000000000000000000000000000000000000000000000002e800000000000000000000000000000000000000000000000000000000000002e900000000000000000000000000000000000000000000000000000000000002ea00000000000000000000000000000000000000000000000000000000000002eb00000000000000000000000000000000000000000000000000000000000002ec00000000000000000000000000000000000000000000000000000000000002ed00000000000000000000000000000000000000000000000000000000000002ee00000000000000000000000000000000000000000000000000000000000002ef00000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002f100000000000000000000000000000000000000000000000000000000000002f200000000000000000000000000000000000000000000000000000000000002f300000000000000000000000000000000000000000000000000000000000002f400000000000000000000000000000000000000000000000000000000000002f500000000000000000000000000000000000000000000000000000000000002f600000000000000000000000000000000000000000000000000000000000002f73700000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000003c100000000000000000000000000000000000000000000000000000000000003c200000000000000000000000000000000000000000000000000000000000003c300000000000000000000000000000000000000000000000000000000000003c400000000000000000000000000000000000000000000000000000000000003c500000000000000000000000000000000000000000000000000000000000003c600000000000000000000000000000000000000000000000000000000000003c700000000000000000000000000000000000000000000000000000000000003c800000000000000000000000000000000000000000000000000000000000003c900000000000000000000000000000000000000000000000000000000000003ca00000000000000000000000000000000000000000000000000000000000003cb00000000000000000000000000000000000000000000000000000000000003cc00000000000000000000000000000000000000000000000000000000000003cd00000000000000000000000000000000000000000000000000000000000003ce00000000000000000000000000000000000000000000000000000000000003cf00000000000000000000000000000000000000000000000000000000000003d000000000000000000000000000000000000000000000000000000000000003d100000000000000000000000000000000000000000000000000000000000003d200000000000000000000000000000000000000000000000000000000000003d300000000000000000000000000000000000000000000000000000000000003d400000000000000000000000000000000000000000000000000000000000003d500000000000000000000000000000000000000000000000000000000000003d600000000000000000000000000000000000000000000000000000000000003d700000000000000000000000000000000000000000000000000000000000003d800000000000000000000000000000000000000000000000000000000000003d900000000000000000000000000000000000000000000000000000000000003da00000000000000000000000000000000000000000000000000000000000003db00000000000000000000000000000000000000000000000000000000000003dc00000000000000000000000000000000000000000000000000000000000003dd00000000000000000000000000000000000000000000000000000000000003de00000000000000000000000000000000000000000000000000000000000003df00000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000003e100000000000000000000000000000000000000000000000000000000000003e200000000000000000000000000000000000000000000000000000000000003e300000000000000000000000000000000000000000000000000000000000003e400000000000000000000000000000000000000000000000000000000000003e500000000000000000000000000000000000000000000000000000000000003e600000000000000000000000000000000000000000000000000000000000003e700000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000003ea00000000000000000000000000000000000000000000000000000000000003eb00000000000000000000000000000000000000000000000000000000000003ec00000000000000000000000000000000000000000000000000000000000003ed00000000000000000000000000000000000000000000000000000000000003ee00000000000000000000000000000000000000000000000000000000000003ef00000000000000000000000000000000000000000000000000000000000003f000000000000000000000000000000000000000000000000000000000000003f100000000000000000000000000000000000000000000000000000000000003f200000000000000000000000000000000000000000000000000000000000003f300000000000000000000000000000000000000000000000000000000000003f400000000000000000000000000000000000000000000000000000000000003f500000000000000000000000000000000000000000000000000000000000003f60200000000000000000000000000000000000000000000000000000000000004c000000000000000000000000000000000000000000000000000000000000004c11000000000000000000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006c100000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006c200000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006c300000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006c400000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006c500000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006c600000000000000000000000000000000000000000000000000000000000006d000000000000000000000000000000000000000000000000000000000000006c700000000000000000000000000000000000000000000000000000000000006d100000000000000000000000000000000000000000000000000000000000006c800000000000000000000000000000000000000000000000000000000000006d200000000000000000000000000000000000000000000000000000000000006c900000000000000000000000000000000000000000000000000000000000006d300000000000000000000000000000000000000000000000000000000000006ca00000000000000000000000000000000000000000000000000000000000006d400000000000000000000000000000000000000000000000000000000000006cb00000000000000000000000000000000000000000000000000000000000006d500000000000000000000000000000000000000000000000000000000000006cc00000000000000000000000000000000000000000000000000000000000006d600000000000000000000000000000000000000000000000000000000000006cd00000000000000000000000000000000000000000000000000000000000006d700000000000000000000000000000000000000000000000000000000000006ce00000000000000000000000000000000000000000000000000000000000006d800000000000000000000000000000000000000000000000000000000000006cf00000000000000000000000000000000000000000000000000000000000006d9000011000000021c000000b00c86563aaf18f39d372daba8a93c1d0523d33332aa8763cddce2c2d6fdf1b533f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb6f8420eb62b2056fc9ba4b629b58c5c54b7927645882de7c98f2b9a7b0da81a610ded805700aa226f61550a89bb37484c5c74c8474bed10bc4723e7e07acfaed0689991f5000000b0243ebdd14aa0c5c42f1a726142cac680d39f781f714e5ba8a108eae428a1fbaffc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb6fc420eb61274702055fae826f528dd56cf9fc7640fc6446ddc3921c48dec4cda489dc6d218628a05fcdcdcb0b3240f04f60371c2fbb955a90deadfbb3ef5d6dd9349d871000000b00bfa610ad4ff82b51dd21bf27b0fd220f197586d7b63833d51897e93d87b4f5b00430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb600430eb62a2cd7b6f182ba4ded15a40f692e70dfbf92895aa300199f521274e7734e0d4e301af19c9864aed7ab10d5bd8f921b3eab859a95d4b1d796031bfeeabdfa1eed0000021c000000b023b2c8a1708754dc15bee2ab149e7b9ca1639d5a422a7b1815afa6a1032b95d704430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb604430eb611e87af07be1773edbcd4da0a1737c7fdd8a69a8ad15413402930897232760fa17d694d622c36bc899c87f4ec7d726dec97d7ae3dec6ff2ab39c929a6dd37299000000b00b06e1c52add86d9555b63ad2cabccbb28fbf9fe8f38026195f3d91a3ddbdc5208430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb608430eb629a0e28717694965d3ba14593b0225fb8d56ae9573dc390ec6b930a44dd7a7762f8efc6cbe4b3def91b546076165d05a7949bfd0a58df70577c2baa79883b915000000b022bf495bc66559004d482a65c63a7636d8c83eeb55fefa3c5a1a0127688c22ce0c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb60c430eb610f4fbaad1bf7b631356955b530f771a14ef0b39c0e9c05846fd631d8887edf116e3159078a16fecd151c7097973217900e21c74f29b7e4ef806ed20d333ff900000021c000000b00a13627f80bb8afd8ce4ab67de47c75560609b8fa30c8185da5e33a0a33c694910430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb610430eb628ad63416d474d8a0b435c13ec9e2095c4bb502687b0b8330b238b2ab338346d2e9b7d2714294213c93e8dc21301caf4b0ae6161b9627629bc2d152dfde4460c000000b021cbca161c435d2484d1722077d670d1102ce07c69d379609e845badcdecafc514430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb614430eb610017c65279d7f874adfdd1604ab71b44c53accad4be3f7c8b67bda3ede87ae815ef964ace7f741108db0ec42b0f1c133846be06066ffd733c7147a738948c87000000b0091fe339d6998f21c46df3228fe3c1ef97c53d20b6e100aa1ec88e27089cf64018430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb618430eb627b9e3fbc32551ae42cca3ce9e3a1b2ffc1ff1b79b8537574f8de5b11898c1642da7fde16a07463800c7d57cc49dc58ee81302f2cd36f54e00976fb46344d3030000021c000000b020d84ad072216148bc5ab9db29726b6b4791820d7da7f884e2eeb634334d3cbc1c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb61c430eb60f0dfd1f7d7b83ab826924d0b6476c4e83b84e5be892bea0cfd2182a534907df14fc1705245d78354064567edcab16ad6fab5f971a447c9780dba22d9df5197e000000b0082c63f42c779345fbf73add417fbc89cf29deb1cab57fce6332e8ad6dfd833720430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb620430eb626c664b6190355d27a55eb894fd615ca33849348af59b67b93f840377df94e5b2cb47e9bbfe54a5c38511d377639c0291f77a483e10b74724501ca3ac8a55ffa000000b01fe4cb8ac7ff656cf3e40195db0e66057ef6239e917c77a9275910ba98adc9b324430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb624430eb60e1a7dd9d35987cfb9f26c8b67e366e8bb1cefecfc673dc5143c72b0b8a994d6140897bf7a3b7c5977ed9e398e471147a71001282e18fbbbc545fcb40355a6750000021c000000b00738e4ae8255976a33808297f31bb724068e8042de89fef2a79d4333d35e102e28430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb628430eb625d2e5706ee159f6b1df3344017210646ae934d9c32e359fd8629abde359db522bc0ff5615c34e806fda64f227d5bac356dc4614f4dff396896c24c12e05ecf1000000b01ef14c451ddd69912b6d49508caa609fb65ac52fa550f6cd6bc36b40fe0e56aa2c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb62c430eb60d26fe9429378bf3f17bb446197f6182f281917e103bbce958a6cd371e0a21cd13151879d019807daf76e5f43fe30be1de74a2b941ed7ae009b0573a68b6336c000000b006456568d8339b8e6b09ca52a4b7b1be3df321d3f25e7e16ec079dba38be9d2530430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb630430eb624df662ac4bf5e1ae9687afeb30e0afea24dd66ad702b4c41cccf54448ba68492acd80106ba152a4a763acacd971b55d8e40e7a608b472bacdd67f47936679e80000021c000000b01dfdccff73bb6db562f6910b3e465b39edbf66c0b92575f1b02dc5c7636ee3a134430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb634430eb60c337f4e7f1590182904fc00cb1b5c1d29e6330f24103c0d9d1127bd836aaec41221993425f784a1e7002daef17f067c15d9444a55c1fa044e1ab1c0ce16c063000000b00551e6232e119fb2a293120d5653ac587557c3650632fd3b3071f8409e1f2a1c38430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb638430eb623ebe6e51a9d623f20f1c2b964aa0598d9b277fbead733e861374fcaae1af54029da00cac17f56c8deecf4678b0daff7c5a589371c88f1df1240d9cdf8c706df000000b01d0a4db9c99971d99a7fd8c5efe255d425240851ccf9f515f498204dc8cf70983c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb63c430eb60b400008d4f3943c608e43bb7cb756b7614ad4a037e4bb31e17b8243e8cb3bbb112e19ee7bd588c61e897569a31b01164d3de5db6996792892850c4733774d5a0000021c000000b0045e66dd83efa3d6da1c59c807efa6f2acbc64f61a077c5f74dc52c7037fb71340430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb640430eb622f8679f707b6663587b0a74164600331117198cfeabb30ca5a1aa51137b823728e68185175d5aed16763c223ca9aa91fd0a2ac8305d710356ab34545e2793d6000000b01c16ce741f7775fdd2092080a17e506e5c88a9e2e0ce743a39027ad42e2ffd8f44430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb644430eb60a4c80c32ad1986098178b762e53515198af76314bb93a5625e5dcca4e2bc8b2103a9aa8d1b38cea5612bd2454b6fbb084a2876c7d6af84cd6ef66cd98d7da51000000b0036ae797d9cda7fb11a5a182b98ba18ce42106872ddbfb83b946ad4d68e0440a48430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb648430eb62204e859c6596a879004522ec7e1facd487bbb1e12803230ea0c04d778dc0f2e27f3023f6d3b5f114dff83dcee45a52c346ecc594431f0279b158edac38820cd0000021c000000b01b234f2e75557a220992683b531a4b0893ed4b73f4a2f35e7d6cd55a93908a864c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb64c430eb60959017d80af9c84cfa0d330dfef4bebd01417c25f8db97a6a503750b38c55a90f471b632791910e8d9c04df0652f64abc0728fd913f77711b59c153fe386748000000b0027768522fabac1f492ee93d6b279c271b85a81841b07aa7fdb107d3ce40d10150430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb650430eb6211169141c376eabc78d99e9797df5677fe05caf2654b1552e765f5dde3c9c2526ff82f9c31963358588cb979fe19fc66bd36dea58066f4bdf7fe96128e8adc4000000b01a2fcfe8cb337e46411baff604b645a2cb51ed0508777282c1d72fe0f8f1177d54430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb654430eb608658237d68da0a9072a1aeb918b46860778b9537362389eaeba91d718ece2a00e539c1d7d6f9532c5254c99b7eef0e4f36bca8ea513f6955fc41bda6398f43f00000fa400000168000000b00183e90c8589b04380b830f81cc396c152ea49a95584f9cc421b625a33a15df858430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb658430eb6201de9ce721572cfff16e1a42b19f001b744fe403a29307972e0b9e4439d291c260c03b418f76759bd121352517d9a60a3380f7b6bdaee7023ea43e78e493abb000000b0193c50a32111826a78a4f7b0b652403d02b68e961c4bf1a706418a675e51a4745c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb65c430eb6077202f22c6ba4cd3eb362a6432741203edd5ae48736b7c2f324ec5d7e4d6f970d601cd7d34d9956fcae9454698aeb7f2ad06c1fb8e875b9a42e7660c8f9813600000168000000b0009069c6db67b467b84178b2ce5f915b8a4eeb3a695978f08685bce09901eaef60430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb660430eb61f2a6a88c7f376f436a0295edcb5ea9beea99fd14dfdaf9db74b146aa8fdb6132518846e6ed56b7df49b5b0d031994fada9cb10c7faf6d9468549e6df3a9c7b2000000b01848d15d76ef868eb02e3f6b67ee3ad73a1b3027302070cb4aabe4edc3b2316b64430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb664430eb6067e83ac8249a8f1763caa60f4c33bba7641fc759b0b36e7378f46e3e3adfc8e0c6c9d92292b9d7b3437dc0f1b26e61962350db0ccbcf4dde898d0e72e5a0e2d00000168000000b0300138f4127758b5a81b0624017ce452e9e77513f6e768a60ed20cfaee6277e768430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb668430eb61e36eb431dd17b186e2971198e51e536260e416261d22ec1fbb56ef10e5e430a24250528c4b36fa22c24a2c7b4b58f951201529d9383ecb8acbef8f4590a54a9000000b017555217cccd8ab2e7b78726198a3571717fd1b843f4efef8f163f742912be626c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb66c430eb6058b0466d827ad15adc5f21ba65f3654ada69e06aedfb60b7bf9a16a490e89850b791e4c7f09a19f6bc123c9ccc2e0b39999af41e09174022d032b6d93ba9b2400000168000000b02f0db9ae68555cd9dfa44ddeb318deed214c16a50abbe7ca533c678153c304de70430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb670430eb61d436bfd73af7f3ca5b2b8d43feddfd05d72e2f375a6ade6401fc97773bed001233185e31a9173c663adea8266518a2f4965f42ea7586bdcf129537abe6ae1a0000000b01661d2d222ab8ed71f40cee0cb26300ba8e4734957c96f13d38099fa8e734b5974430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb674430eb6049785212e05b139e54f39d657fb30eee50b3f97c2b4352fc063fbf0ae6f167c0a859f06d4e7a5c3a34a6b847e5edb4dd0fe50d2f465f326716d85f3f91b281b00000168000000b02e1a3a68be3360fe172d959964b4d98758b0b8361e9066ee97a6c207b92391d578430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb678430eb61c4fecb7c98d8360dd3c008ef189da6a94d78484897b2d0a848a23fdd91f5cf8223e069d706f77ea9b37323d17ed84c980ca95bfbb2ceb013593ae0123cb6e97000000b0156e538c788992fb56ca169b7cc22aa5e04914da6b9dee3817eaf480f3d3d8507c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb67c430eb603a405db83e3b55e1cd8819109972b891c6fe128d688b45404ce567713cfa37309921fc12ac5a9e7dad3b33f2ffad5e80862f264083a724ab5d7e07a5e7bb51200000168000000b02d26bb23141165224eb6dd541650d421901559c73264e612dc111c8e1e841ecc80430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb680430eb61b5c6d721f6b878514c54849a325d504cc3c26159d4fac2ec8f47e843e7fe9ef214a8757c64d7c0ed2c079f7c9897f63b82f3750cf016a2579fe0887892bfb8e000000b0147ad446ce67971f8e535e562e5e254017adb66b7f726d5c5c554f075934654784430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb684430eb602b08695d9c1b9825461c94bbb33262353d482b9ea5d33784938b0fd7930306a089ea07b80a3ae0c125cfaf9e196d0823fc793f51c0ef16efa423b00c3dc420900000168000000b02c333bdd69ef69468640250ec7eccebbc779fb5846396537207b771483e4abc388430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb688430eb61a68ee2c75498ba94c4e900454c1cf9f03a0c7a6b1242b530d5ed90aa3e076e6205708121c2b80330a49c1b27b2579fdef93d8e1e2d5e949be68630dee8c8885000000b01387550124459b43c5dca610dffa1fda4f1257fc9346ec80a0bfa98dbe94f23e8c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb68c430eb601bd07502f9fbda68beb11066ccf20bd8b39244afe31b29c8da30b83de90bd6107ab2135d681b23049e642b49332cb1c772c35862fe370933eac9587293ccf0000000168000000b02b3fbc97bfcd6d6abdc96cc97988c955fede9ce95a0de45b64e5d19ae94538ba90430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb690430eb619756ee6cb278fcd83d7d7bf065dca393b056937c4f8aa7751c93391094103dd1f6388cc7209845741d3096d2cc1749826f87a72f6aa686e02d2bd9453ed157c000000b01293d5bb7a239f67fd65edcb91961a748676f98da71b6ba4e52a041423f57f3594430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb694430eb600c9880a857dc1cac37458c11e6b1b57c29dc5dc120631c0d20d660a43f14a5806b7a1f02c5fb654816f8a6f44cec5b6ae90d71743b7efb78316f00d8e9d5bf700000168000000b02a4c3d5215ab718ef552b4842b24c3f036433e7a6de2637fa9502c214ea5c5b198430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb698430eb61881efa1210593f1bb611f79b7f9c4d3726a0ac8d8cd299b96338e176ea190d41e700986c7e7887b795c5127de5d6f325e5d1c040a7ee792473d181ab94da273000000b011a05675d001a38c34ef35864332150ebddb9b1ebaefeac929945e9a89560c2c9c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb69c430eb6303a5737bc8d6618b34de63251886e4f22364fb59f9421765a59b6249951d75005c422aa823dba78b8f8d229f66ac050e5f578a8578c6edbc7814a93f3fde8ee00000168000000b02958be0c6b8975b32cdbfc3edcc0be8a6da7e00b81b6e2a3edba86a7b40652a8a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6a0430eb6178e705b76e39815f2ea67346995bf6da9ceac59eca1a8bfda9de89dd4021dcb1d7c8a411dc58c9fb0e598e28ff969cc95c1bd951e5366b68ba772a11eae2f6a000000b010acd73025dfa7b06c787d40f4ce0fa8f5403cafcec469ed6dfeb920eeb69923a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb6a4430eb62f46d7f2126b6a3cead72ded032468e9599af146b368a09a9ec410aafeb2644704d0a364d81bbe9cf08219e4a806baeb1d5a1a396b60ee000beba51a595e75e500000168000000b028653ec6c16779d7646543f98e5cb924a50c819c958b61c83224e12e1966df9fa8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6a8430eb6169af115ccc19c3a2a73aeef1b31ba07e1334deb007627e41f0843243962aac21c890afb73a390c3e86ee09d41956466cd265f263227e5dad011cd27840ebc61000000b00fb957ea7bbdabd4a401c4fba66a0a432ca4de40e298e911b26913a75417261aac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb6ac430eb62e5358ac68496e61226075a7b4c0638390ff92d7c73d1fbee32e6b316412f13e03dd241f2df9c2c1280b619f59a2b58554bebbca7f356d245055ffa0bebf02dc380000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000030100000000000000000000000000000000000000000000000000000000000003020000000000000000000000000000000000000000000000000000000000000303000000000000000000000000000000000000000000000000000000000000030400000000000000000000000000000000000000000000000000000000000003050000000000000000000000000000000000000000000000000000000000000306000000000000000000000000000000000000000000000000000000000000030700000000000000000000000000000000000000000000000000000000000003080000000000000000000000000000000000000000000000000000000000000309000000000000000000000000000000000000000000000000000000000000030a000000000000000000000000000000000000000000000000000000000000030b000000000000000000000000000000000000000000000000000000000000030c000000000000000000000000000000000000000000000000000000000000030d000000000000000000000000000000000000000000000000000000000000030e000000000000000000000000000000000000000000000000000000000000030f0000000000000000000000000000000000000000000000000000000000000310000000000000000000000000000000000000000000000000000000000000031100000000000000000000000000000000000000000000000000000000000003120000000000000000000000000000000000000000000000000000000000000313000000000000000000000000000000000000000000000000000000000000031400000000000000000000000000000000000000000000000000000000000003150000000000000000000000000000000000000000000000000000000000000316000000000000000000000000000000000000000000000000000000000000031700000000000000000000000000000000000000000000000000000000000003180000000000000000000000000000000000000000000000000000000000000319000000000000000000000000000000000000000000000000000000000000031a000000000000000000000000000000000000000000000000000000000000031b000000000000000000000000000000000000000000000000000000000000031c000000000000000000000000000000000000000000000000000000000000031d000000000000000000000000000000000000000000000000000000000000031e000000000000000000000000000000000000000000000000000000000000031f0000000000000000000000000000000000000000000000000000000000000320000000000000000000000000000000000000000000000000000000000000032100000000000000000000000000000000000000000000000000000000000003220000000000000000000000000000000000000000000000000000000000000323000000000000000000000000000000000000000000000000000000000000032400000000000000000000000000000000000000000000000000000000000003250000000000000000000000000000000000000000000000000000000000000326000000000000000000000000000000000000000000000000000000000000032700000000000000000000000000000000000000000000000000000000000003280000000000000000000000000000000000000000000000000000000000000329000000000000000000000000000000000000000000000000000000000000032a000000000000000000000000000000000000000000000000000000000000032b000000000000000000000000000000000000000000000000000000000000032c000000000000000000000000000000000000000000000000000000000000032d000000000000000000000000000000000000000000000000000000000000032e000000000000000000000000000000000000000000000000000000000000032f00000000000000000000000000000000000000000000000000000000000003300000000000000000000000000000000000000000000000000000000000000331000000000000000000000000000000000000000000000000000000000000033200000000000000000000000000000000000000000000000000000000000003330000000000000000000000000000000000000000000000000000000000000334000000000000000000000000000000000000000000000000000000000000033500000000000000000000000000000000000000000000000000000000000003360000000000000000000000000000000000000000000000000000000000000337370000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040100000000000000000000000000000000000000000000000000000000000004020000000000000000000000000000000000000000000000000000000000000403000000000000000000000000000000000000000000000000000000000000040400000000000000000000000000000000000000000000000000000000000004050000000000000000000000000000000000000000000000000000000000000406000000000000000000000000000000000000000000000000000000000000040700000000000000000000000000000000000000000000000000000000000004080000000000000000000000000000000000000000000000000000000000000409000000000000000000000000000000000000000000000000000000000000040a000000000000000000000000000000000000000000000000000000000000040b000000000000000000000000000000000000000000000000000000000000040c000000000000000000000000000000000000000000000000000000000000040d000000000000000000000000000000000000000000000000000000000000040e000000000000000000000000000000000000000000000000000000000000040f0000000000000000000000000000000000000000000000000000000000000410000000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004120000000000000000000000000000000000000000000000000000000000000413000000000000000000000000000000000000000000000000000000000000041400000000000000000000000000000000000000000000000000000000000004150000000000000000000000000000000000000000000000000000000000000416000000000000000000000000000000000000000000000000000000000000041700000000000000000000000000000000000000000000000000000000000004180000000000000000000000000000000000000000000000000000000000000419000000000000000000000000000000000000000000000000000000000000041a000000000000000000000000000000000000000000000000000000000000041b000000000000000000000000000000000000000000000000000000000000041c000000000000000000000000000000000000000000000000000000000000041d000000000000000000000000000000000000000000000000000000000000041e000000000000000000000000000000000000000000000000000000000000041f0000000000000000000000000000000000000000000000000000000000000420000000000000000000000000000000000000000000000000000000000000042100000000000000000000000000000000000000000000000000000000000004220000000000000000000000000000000000000000000000000000000000000423000000000000000000000000000000000000000000000000000000000000042400000000000000000000000000000000000000000000000000000000000004250000000000000000000000000000000000000000000000000000000000000426000000000000000000000000000000000000000000000000000000000000042700000000000000000000000000000000000000000000000000000000000004280000000000000000000000000000000000000000000000000000000000000429000000000000000000000000000000000000000000000000000000000000042a000000000000000000000000000000000000000000000000000000000000042b000000000000000000000000000000000000000000000000000000000000042c000000000000000000000000000000000000000000000000000000000000042d000000000000000000000000000000000000000000000000000000000000042e000000000000000000000000000000000000000000000000000000000000042f00000000000000000000000000000000000000000000000000000000000004300000000000000000000000000000000000000000000000000000000000000431000000000000000000000000000000000000000000000000000000000000043200000000000000000000000000000000000000000000000000000000000004330000000000000000000000000000000000000000000000000000000000000434000000000000000000000000000000000000000000000000000000000000043500000000000000000000000000000000000000000000000000000000000004360200000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000501100000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000701000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000702000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000703000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000704000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000705000000000000000000000000000000000000000000000000000000000000070f00000000000000000000000000000000000000000000000000000000000007060000000000000000000000000000000000000000000000000000000000000710000000000000000000000000000000000000000000000000000000000000070700000000000000000000000000000000000000000000000000000000000007110000000000000000000000000000000000000000000000000000000000000708000000000000000000000000000000000000000000000000000000000000071200000000000000000000000000000000000000000000000000000000000007090000000000000000000000000000000000000000000000000000000000000713000000000000000000000000000000000000000000000000000000000000070a0000000000000000000000000000000000000000000000000000000000000714000000000000000000000000000000000000000000000000000000000000070b0000000000000000000000000000000000000000000000000000000000000715000000000000000000000000000000000000000000000000000000000000070c0000000000000000000000000000000000000000000000000000000000000716000000000000000000000000000000000000000000000000000000000000070d0000000000000000000000000000000000000000000000000000000000000717000000000000000000000000000000000000000000000000000000000000070e0000000000000000000000000000000000000000000000000000000000000718000000000000000000000000000000000000000000000000000000000000070f0000000000000000000000000000000000000000000000000000000000000719000011000000021c000000b02771bf8117457dfb9bee8bb43ff8b3bedc71232da95fe0ec768f3bb47ec76c96b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb6b0430eb615a771d0229fa05e61fcf6a9cccdb4a21897ef7c144aa70863729daa9ec337b91b958bb5c98194e81ff82857f3315f01048b00b745fc64ff147c27ade96f4958000000b00ec5d8a4d19baff8db8b0cb6580604dd64097fd1f66d6835f6d36e2db977b311b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb6b4430eb62d5fd966be27728559e9bd62665c5e1dc8643468db119ee32798c5b7c9737e3502e9a4d983d7c6e55f94a95a0b3eb01f8c235d5b9309ec4894c05a27241f8fd3000000b0267e403b6d23821fd377d36ef194ae5913d5c4bebd346010baf9963ae427f98db8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb6b8430eb614b3f28a787da48299863e647e69af3c4ffc910d281f262ca7dcf8310423c4b01aa20c701f5f990c57817012a4cd599b3befa24859d0e42358e682344ecfd64f0000021c000000b00dd2595f2779b41d1314547109a1ff779b6e21630a41e75a3b3dc8b41ed84008bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb6bc430eb62c6c5a21140576a99173051d17f858b7ffc8d5f9eee61e076c03203e2ed40b2c01f62593d9b5cb09971df114bcdaaab9c387feeca6de6b6cd92ab4ad89801cca000000b0258ac0f5c30186440b011b29a330a8f34b3a664fd108df34ff63f0c149888684c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb6c0430eb613c07344ce5ba8a6d10f861f3005a9d68761329e3bf3a550ec4752b7698451a719ae8d2a753d9d308f0ab7cd56695435735443d96da563479d50dcbab4306346000000b00cdeda197d57b8414a9d9c2bbb3dfa11d2d2c2f41e16667e7fa8233a8438ccffc4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb6c4430eb62b78dadb69e37acdc8fc4cd7c9945352372d778b02ba9d2bb06d7ac4943498230102a64e2f93cf2dcea738cf6e76a553faeca07dbab2ea911d950f33eee0a9c10000021c000000b0249741b018df8a68428a62e454cca38d829f07e0e4dd5e5943ce4b47aee9137bc8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb6c8430eb612ccf3ff2439accb0898cdd9e1a1a470bec5d42f4fc8247530b1ad3dcee4de9e18bb0de4cb1ba154c693ff8808054ecfaab8e56a8179e26be1bb37411990f03d000000b00beb5ad3d335bc658226e3e66cd9f4ac0a37648531eae5a2c4127dc0e99959f6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb6cc430eb62a855b95bfc17ef2008594927b304dec6e92191c168f1c4ff4d7d54af995251a000f27088571d3520630808a20129fee3251420ece8769b561ff69ba544136b8000000b023a3c26a6ebd8e8c7a13aa9f06689e27ba03a971f8b1dd7d8838a5ce1449a072d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb6d0430eb611d974b97a17b0ef40221594933d9f0af62a75c0639ca399751c07c434456b9517c78e9f20f9a578fe1d4742b9a14969e21d86fb954e6190262591c77ef17d340000021c000000b00af7db8e2913c089b9b02ba11e75ef46419c061645bf64c7087cd8474ef9e6edd4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb6d4430eb62991dc50159f8316380edc4d2ccc4886a5f6baad2a639b7439422fd15ef5b2112f7ff635bc81779ff60a0dfb532ff2e591e9cbe85c15596aea4bb9d4a9a1c3b0000000b022b04324c49b92b0b19cf259b80498c1f1684b030c865ca1cca3005479aa2d69d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb6d8430eb610e5f573cff5b51377ab5d4f44d999a52d8f1751777122bdb986624a99a5f88c16d40f5976d7a99d35a68efd6b3d44041982288ca922e0b46a8fec4de4520a2b000000b00a045c487ef1c4adf139735bd011e9e07900a7a75993e3eb4ce732cdb45a73e4dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6dc430eb6289e5d0a6b7d873a6f982407de684320dd5b5c3e3e381a987dac8a57c4563f082e8c76f0125f7bc42d9355b604cbed7fc94e6d796fe9d88f2eb6145b0f0250a70000021c000000b021bcc3df1a7996d4e9263a1469a0935c28ccec94205adbc6110d5adadf0aba60e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb6e0430eb60ff2762e25d3b937af34a509f675943f64f3b8e28b45a1e1fdf0bcd0ff06858315e09013ccb5adc16d2fd6b81cd93e9e50e6ca1dbcf75fd8aefa46d449b29722000000b00910dd02d4cfc8d228c2bb1681ade47ab06549386d68630f91518d5419bb00dbe4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb6e4430eb627aaddc4c15b8b5ea7216bc290043dbb14bffdcf520c99bcc216e4de29b6cbff2d98f7aa683d7fe8651c9d70b667e81a00b30f0a83be57b373206ee17462dd9e000000b020c9449970579af920af81cf1b3c8df660318e25342f5aea5577b561446b4757e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb6e8430eb60efef6e87bb1bd5be6bdecc4a8118ed99c585a739f1a2106425b17576467127a14ed10ce2293b1e5a4b91e72ce753938884b6baed0cbdefcf364a15aaf1324190000021c000000b0081d5dbd2aadccf6604c02d13349df14e7c9eac9813ce233d5bbe7da7f1b8dd2ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb6ec430eb626b75e7f17398f82deaab37d41a038554c249f6065e118e106813f648f1758f62ca57864be1b840c9ca5e52b6803e2b43817b09b9792d6d7b78ac967d9c36a95000000b01fd5c553c6359f1d5838c989ccd8889097962fb64803da0e99e20fe7a9cbd44ef0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb6f0430eb60e0b77a2d18fc1801e47347f59ad8973d3bcfc04b2eea02a86c571ddc9c79f7113f991887871b609dc42662d801133d2bfb00d3fe4a05e2137cefbe11473b110000000b00729de77808bd11a97d54a8be4e5d9af1f2e8c5a951161581a264260e47c1ac9f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb6f4430eb625c3df396d1793a71633fb37f33c32ef838940f179b598054aeb99eaf477e5ed2bb1f91f13f98830d42f2ce6199fdd4e6f7c522cab6755fbfbf523ee3f23f78c0000021c000000b01ee2460e1c13a3418fc211447e74832acefad1475bd85932de4c6a6e0f2c6145f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb6f8430eb60d17f85d276dc5a455d07c3a0b49840e0b219d95c6c31f4ecb2fcc642f282c6813061242ce4fba2e13cbade831ad2e6cf714aed0f874dd457c39566779d43e07000000b006365f31d669d53ecf5e92469681d44956932deba8e5e07c5e909ce749dca7c0fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb6fc430eb624d05ff3c2f597cb4dbd42f2a4d82d89baede2828d8a17298f55f47159d872e42abe79d969d78c550bb874a0cb3bd7e8a6e0f3bdbf3bd520405f7e74a4848483000000b01e5650de41fa32597666818e504838469cbef6822cb478a252f3262ae9b5fb6d00440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb600440eb60c2479177d4bc9c88d59c3f4bce57ea842863f26da979e730f9a26ea9488b95f121292fd242dbe524b54f5a2e34929072e7950620c495c69c0a3b0eddf34cafe0000021c000000b005aa6a01fc506456b6030290685589652457532679c1ffebd33758a4246641e804440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb604440eb624446ac3e8dc26e33461b33c76abe2a588b207bd5e66369903fcb02e34620d0c2a3284a98fbe1b6cf25ce4ea9d0f8d0474a518f89017f48fb5063a317f0e1eab000000b01d62d19897d8367dadefc94901e432e0d42398134088f7c6975d80b14f16886408440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb608440eb60b9883e7a33258e073fe343e8eb933c4104a6461ab73bde28440e2a76f12538711869dcd4a144d6a31f965ecb51cde22fc3d759cdd257bd9354a6caab9be6526000000b004b6eabc522e687aed8c4a4b19f183ff5bbbf4b78d967f1017a1b32a89c6cedf0c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb60c440eb62350eb7e3eba2b076beafaf72847dd3fc016a94e723ab5bd48670ab499c29a03293f0563e59c1f9129e62ca54eab879eac09ba89a3ec73b3f97094b7e46eaba200000fa400000168000000b01c6f5252edb63aa1e5791103b3802d7b0b8839a4545d76eadbc7db37b477155b10440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb610440eb60aa504a1f9105d04ab877bf940552e5e47af05f2bf483d06c8ab3d2dd472e07e10931e879ff2518e6982ada766b8d8bd33a2172df0f9fafd79b4c7311f1ef21d000000b003c36b76a80c6c9f25159205cb8d7e9993209648a16afe345c0c0db0ef275bd614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb614440eb6225d6c3894982f2ba37442b1d9e3d7d9f77b4adf860f34e18cd1653aff2326fa284b861e3b7a23b5616f746000478238e36e5c1ab7c0f2d83ddaef3e49cf389900000168000000b01b7bd30d43943ec61d0258be651c281542ecdb356831f60f203235be19d7a25218440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb618440eb609b1855c4eee6128e310c3b3f1f128f87f13a783d31cbc2b0d1597b439d36d750f9f9f41f5d055b2a10bf5621854d3576b06b8bf04ce7a21be1f21b7847f7f14000000b002cfec30fdea70c35c9ed9c07d297933ca8537d9b53f7d58a07668375487e8cd1c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb61c440eb62169ecf2ea76334fdafd8a6c8b7fd2742edfec7099e3b405d13bbfc16483b3f1275806d8915827d998f8bc1ab1e37cd31ad2fdabcb9571fc824549c4af2fc59000000168000000b01a8853c7997242ea548ba07916b822af7a517cc67c067533649c90447f382f4920440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb620440eb608be0616a4cc654d1a9a0b6ea38d2392b6784914e6f13b4f517ff23a9f33fa6c0eac1ffc4bae59d6d8953d1cc9f0cdf1a26b5a5018a2f94602897c3de9e00c0b000000b001dc6ceb53c874e79428217b2ec573ce01e9d96ac913fc7ce4e0c2bdb9e875c424440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb624440eb620766dad405437741286d2273d1bcd0e66448e01adb8332a15a61a47c9e440e826648792e7362bfdd08203d5637f776d52379f3cdf69f120c6afa44b1490528700000168000000b01994d481ef50470e8c14e833c8541d49b1b61e578fdaf457a906eacae498bc4028440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb628440eb607ca86d0faaa69715223532955291e2ceddceaa5fac5ba7395ea4cc1049487630db8a0b6a18c5dfb101e84d77b8cc88bd9cffbe12c77786a46f3d6c44f409902000000b000e8eda5a9a6790bcbb16935e0616e68394e7afbdce87ba1294b1d441f4902bb2c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb62c440eb61f82ee6796323b984a1019e1eeb7c7a89da92f92c18cb24e5a1074ce2f44cddf2571084d3d143022080b4b90151b7207899c40cdf33e70450b19fed179f0df7e00000168000000b018a1553c452e4b32c39e2fee79f017e3e91abfe8a3af737bed71455149f9493730440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb630440eb606d7078b50886d9589ac9ae406c518c725418c370e9a3997da54a74769f5145a0cc52170f76a621f47a7cc922d28c32611349d72404bf78e8b5e314ab4a125f9000000b03059bcd2e0b61d59bb8af6a7137ec15f98e704d56a766b56b1976d5e74a98fb334440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb634440eb61e8f6f21ec103fbc8199619ca053c242d50dd123d56131729e7acf5494a55ad6247d890792f234463f94934ac6b76ca1c100e25f0712ef694f845957df516c7500000168000000b017add5f69b0c4f56fb2777a92b8c127e207f6179b783f2a031db9fd7af59d62e38440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb638440eb605e38845a66671b9c135e29eb86113615ca62dc8226eb8bc1ebf01cdcf55a1510bd1a22b4d4866437f31144cdec4bdc048993f03542076b2cfc88bd11a01b2f0000000b02f663d8d3694217df3143e61c51abbf9d04ba6667e4aea7af601c7e4da0a1caa3c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb63c440eb61d9befdc41ee43e0b922a95751efbcdd0c7272b4e935b096e2e529dafa05e7cd238a09c1e8d0386a771ddb057853673bf86583f01ae76e8d93eeb3de44b1f96c00000168000000b016ba56b0f0ea537b32b0bf63dd280d1857e4030acb5871c47645fa5e14ba632540440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb640440eb604f008fffc4475ddf8bf2a5969fd0dfb940acf59364337e063295c5434b62e480ade22e5a3266a67b6ba5c079060b85a7ffde09467f4f5d71432e6577f623fe7000000b02e72be478c7225a22a9d861c76b6b69407b047f7921f699f3a6c226b3f6aa9a144440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb644440eb61ca8709697cc4804f0abf112038bb77743d71445fd0a2fbb274f84615f6674c422968a7c3eae3c8eaea722c029ef61d62fca25812ebbedb1d8590e64aa12866300000168000000b015c6d76b46c8579f6a3a071e8ec407b28f48a49bdf2cf0e8bab054e47a1af01c48440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb648440eb603fc89ba52227a02304872141b990895cb6f70ea4a17b704a793b6da9a16bb3f09eaa39ff9046e8bee43a3c241fcb2f4b76282257bc974fb589d40dde4c2ccde000000b02d7f3f01e25029c66226cdd72852b12e3f14e988a5f3e8c37ed67cf1a4cb36984c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb64c440eb61bb4f150edaa4c29283538ccb527b2117b3bb5d710deaedf6bb9dee7c4c701bb21a30b36948c40b2e6306a7adb8b5c70672ec71242906cd61cc368eb0f73135a00000168000000b014d358259ca65bc3a1c34ed94060024cc6ad462cf301700cff1aaf6adf7b7d1350440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb650440eb603090a74a8007e2667d1b9cecd35033002d4127b5dec3628ebfe1160ff77483608f7245a4ee272b025cceb7cf398ad8eeec723b68f9df41f9d079b644a2359d5000000b02c8bbfbc382e2dea99b01591d9eeabc876798b19b9c867e7c340d7780a2bc38f54440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb654440eb61ac1720b4388504d5fbe808766c3acabb2a0576824b32e03b024396e2a278eb220af8bf0ea6a44d71db9b2358d27570a9e9368a35664ebfa612dc37174d3a05100000168000000b013dfd8dff2845fe7d94c9693f1fbfce6fe11e7be06d5ef31438509f144dc0a0a58440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb658440eb602158b2efdde824a9f5b01897ed0fdca3a38b40c71c0b54d30686be764d7d52d0803a514a4c076d45d563337a534a829262bc547a3727343e171f5eaaf83e6cc000000b02b9840768e0c320ed1395d4c8b8aa662adde2caacd9ce70c07ab31fe6f8c50865c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb65c440eb619cdf2c5996654719747c842185fa745ea04f8f93887ad27f48e93f48f881ba91fbc0cab404848fb5542f9f03ec351a4d5f80a346a396b1ea5981df7da342d4800000168000000b012ec599a4862640c10d5de4ea397f7813576894f1aaa6e5587ef6477aa3c970160440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb660440eb601220be953bc866ed6e44944306cf864719d559d8595347174d2c66dca386224071025cefa9e7af894df7af256d0a2c35d9066d8b746f26825dc507114e473c3000000b02aa4c130e3ea363308c2a5073d26a0fce542ce3be17166304c158c84d4ecdd7d64440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb664440eb618da737fef445895ced10ffcc9fba1e021699a8a4c5c2c4c38f8ee7af4e8a8a01ec88d6596264d1f8ccc41aaf05f4c3f0d5cabc57e0dea42ea02787e3f94ba3f", "txsEffectsHash": "0x80dc9d246537063813894f7edb41c694fbd803946807e6e3e875a6bbd91b531b", "decodedHeader": { "contentCommitment": { - "inHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "inHash": "0x8e7d8bf0ef7ebd1607cc7ff9f2fbacf4574ee5b692a5a5ac1e7b1594067b9049", "outHash": "0x3c00faec8dc481e71433eb21f1dd016134bf403950c146783ba1928cddcb315d", "txTreeHeight": 2, "txsEffectsHash": "0x80dc9d246537063813894f7edb41c694fbd803946807e6e3e875a6bbd91b531b" @@ -65,14 +65,14 @@ "globalVariables": { "blockNumber": 2, "chainId": 31337, - "timestamp": 1710254426, + "timestamp": 1710325361, "version": 1, "coinbase": "0xa43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb6", "feeRecipient": "0x15a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb" }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x1ba503ae8f13b59815a58d204ca967063570ef165cb4d87b7609bce726f51410" + "root": "0x002112631bea3a8334e954f4de111c9158cafeab265fc94ee695b3b4d20f0427" }, "stateReference": { "l1ToL2MessageTree": { @@ -95,8 +95,8 @@ } } }, - "header": "0x1ba503ae8f13b59815a58d204ca967063570ef165cb4d87b7609bce726f5141000000002000000000000000000000000000000000000000000000000000000000000000280dc9d246537063813894f7edb41c694fbd803946807e6e3e875a6bbd91b531b00000000000000000000000000000000000000000000000000000000000000003c00faec8dc481e71433eb21f1dd016134bf403950c146783ba1928cddcb315d06c76caee115a61eeb6788977c68a3bea359061b678a1a4f5ffde13e0451717b00000020023ef973dbaa366409f7a01a4ced696227685ce75e57b510d0e7015ebfa72c5000000200231b77b7e0311a71fae5cec0f0281816950f94a24bfc2e67c5ae8619c6ed4c88000002802ae3a1bf2752c8c8bd6741bb3fd0d9e3811dbf7681454436125ccb7afeca31c9000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065f0695aa43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb615a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb", + "header": "0x002112631bea3a8334e954f4de111c9158cafeab265fc94ee695b3b4d20f042700000002000000000000000000000000000000000000000000000000000000000000000280dc9d246537063813894f7edb41c694fbd803946807e6e3e875a6bbd91b531b8e7d8bf0ef7ebd1607cc7ff9f2fbacf4574ee5b692a5a5ac1e7b1594067b90493c00faec8dc481e71433eb21f1dd016134bf403950c146783ba1928cddcb315d06c76caee115a61eeb6788977c68a3bea359061b678a1a4f5ffde13e0451717b00000020023ef973dbaa366409f7a01a4ced696227685ce75e57b510d0e7015ebfa72c5000000200231b77b7e0311a71fae5cec0f0281816950f94a24bfc2e67c5ae8619c6ed4c88000002802ae3a1bf2752c8c8bd6741bb3fd0d9e3811dbf7681454436125ccb7afeca31c9000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065f17e71a43e0eb6a43e0eb6a43e0eb6a43e0eb6a43e0eb615a9c4f4c75d79ce22330ca2cdb6c1a6ede1f6d94ba28016eeb25e5578913ccb", "l1ToL2MessagesHash": "0xa10cc8559615be5a44cfb608374b1f84fd11cdb5844ebffafd92a77c068350f1", - "publicInputsHash": "0x2fc68717ed22432d1f847c66d73d0bad1bff27fac3e2007a5848fecf97001c99" + "publicInputsHash": "0x1cf2b46b77f14cccda98bf1892afb0c0dbd3bfb60aefab5c167a0dc479348993" } } \ No newline at end of file diff --git a/l1-contracts/test/merkle/Merkle.t.sol b/l1-contracts/test/merkle/Merkle.t.sol index f430b72e43f..60721c97254 100644 --- a/l1-contracts/test/merkle/Merkle.t.sol +++ b/l1-contracts/test/merkle/Merkle.t.sol @@ -6,19 +6,17 @@ import {Test} from "forge-std/Test.sol"; import {NaiveMerkle} from "./Naive.sol"; import {FrontierMerkle} from "./../../src/core/messagebridge/frontier_tree/Frontier.sol"; +import {Constants} from "../../src/core/libraries/ConstantsGen.sol"; contract MerkleTest is Test { - NaiveMerkle internal merkle; - FrontierMerkle internal frontier; + function setUp() public {} - uint256 public constant DEPTH = 10; + function testFrontier() public { + uint256 depth = 10; - function setUp() public { - merkle = new NaiveMerkle(DEPTH); - frontier = new FrontierMerkle(DEPTH); - } + NaiveMerkle merkle = new NaiveMerkle(depth); + FrontierMerkle frontier = new FrontierMerkle(depth); - function testFrontier() public { uint256 upper = frontier.SIZE(); for (uint256 i = 0; i < upper; i++) { bytes32 leaf = sha256(abi.encode(i + 1)); @@ -27,4 +25,77 @@ contract MerkleTest is Test { assertEq(merkle.computeRoot(), frontier.root(), "Frontier Roots should be equal"); } } + + // Checks whether sha root matches output of base parity circuit + function testRootMatchesBaseParity() public { + uint256[4] memory msgs = [ + 0x151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d78393537039, + 0x14c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e, + 0x1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a1, + 0x2806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e0 + ]; + + // We can't use Constants.NUM_MSGS_PER_BASE_PARITY directly when defining the array so we do the check here to + // ensure it does not get outdated. + assertEq( + msgs.length, + Constants.NUM_MSGS_PER_BASE_PARITY, + "NUM_MSGS_PER_BASE_PARITY changed, update msgs." + ); + + uint256 treeHeight = 2; // log_2(NUM_MSGS_PER_BASE_PARITY) + // We don't have log_2 directly accessible in solidity so I just do the following check here to ensure + // the hardcoded value is not outdated. + assertEq( + 2 ** treeHeight, + Constants.NUM_MSGS_PER_BASE_PARITY, + "Base parity circuit subtree height changed, update treeHeight." + ); + + FrontierMerkle frontier = new FrontierMerkle(treeHeight); + + for (uint256 i = 0; i < msgs.length; i++) { + frontier.insertLeaf(bytes32(msgs[i])); + } + + bytes32 expectedRoot = 0xb3a3fc1968999f2c2d798b900bdf0de41311be2a4d20496a7e792a521fc8abac; + assertEq(frontier.root(), expectedRoot, "Root does not match base parity circuit root"); + } + + // Checks whether sha root matches output of root parity circuit + function testRootMatchesRootParity() public { + // sha256 roots coming out of base parity circuits + uint256[4] memory baseRoots = [ + 0xb3a3fc1968999f2c2d798b900bdf0de41311be2a4d20496a7e792a521fc8abac, + 0x43f78e0ebc9633ce336a8c086064d898c32fb5d7d6011f5427459c0b8d14e91f, + 0x024259b6404280addcc9319bc5a32c9a5d56af5c93b2f941fa326064fbe9636c, + 0x53042d820859d80c474d4694e03778f8dc0ac88fc1c3a97b4369c1096e904ae7 + ]; + + // We can't use Constants.NUM_BASE_PARITY_PER_ROOT_PARITY directly when defining the array so we do the check here + // to ensure it does not get outdated. + assertEq( + baseRoots.length, + Constants.NUM_BASE_PARITY_PER_ROOT_PARITY, + "NUM_BASE_PARITY_PER_ROOT_PARITY changed, update baseRoots." + ); + + uint256 treeHeight = 2; // log_2(NUM_BASE_PARITY_PER_ROOT_PARITY) + // We don't have log_2 directly accessible in solidity so I just do the following check here to ensure + // the hardcoded value is not outdated. + assertEq( + 2 ** treeHeight, + Constants.NUM_BASE_PARITY_PER_ROOT_PARITY, + "Root parity circuit subtree height changed, update treeHeight." + ); + + FrontierMerkle frontier = new FrontierMerkle(treeHeight); + + for (uint256 i = 0; i < baseRoots.length; i++) { + frontier.insertLeaf(bytes32(baseRoots[i])); + } + + bytes32 expectedRoot = 0x8e7d8bf0ef7ebd1607cc7ff9f2fbacf4574ee5b692a5a5ac1e7b1594067b9049; + assertEq(frontier.root(), expectedRoot, "Root does not match root parity circuit root"); + } } diff --git a/noir-projects/noir-protocol-circuits/Nargo.toml b/noir-projects/noir-protocol-circuits/Nargo.toml index 3be5d529394..ee1eda1c511 100644 --- a/noir-projects/noir-protocol-circuits/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/Nargo.toml @@ -1,6 +1,9 @@ [workspace] members = [ "crates/types", + "crates/parity-base", + "crates/parity-lib", + "crates/parity-root", "crates/private-kernel-lib", "crates/private-kernel-init", "crates/private-kernel-init-simulated", diff --git a/noir-projects/noir-protocol-circuits/crates/parity-base/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/parity-base/Nargo.toml new file mode 100644 index 00000000000..35d36fe1e56 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-base/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "parity_base" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +parity_lib = { path = "../parity-lib" } +types = { path = "../types" } diff --git a/noir-projects/noir-protocol-circuits/crates/parity-base/src/main.nr b/noir-projects/noir-protocol-circuits/crates/parity-base/src/main.nr new file mode 100644 index 00000000000..8fea34b8cf8 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-base/src/main.nr @@ -0,0 +1,5 @@ +use dep::parity_lib::{BaseParityInputs, ParityPublicInputs}; + +fn main(inputs: BaseParityInputs) -> pub ParityPublicInputs { + inputs.base_parity_circuit() +} diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/parity-lib/Nargo.toml new file mode 100644 index 00000000000..45d8bf4b72f --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/Nargo.toml @@ -0,0 +1,8 @@ +[package] +name = "parity_lib" +type = "lib" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +types = { path = "../types" } diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base.nr new file mode 100644 index 00000000000..962604a949f --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base.nr @@ -0,0 +1 @@ +mod base_parity_inputs; \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr new file mode 100644 index 00000000000..13bb7b0712c --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/base/base_parity_inputs.nr @@ -0,0 +1,60 @@ +use crate::{ + parity_public_inputs::ParityPublicInputs, + utils::sha256_merkle_tree::Sha256MerkleTree, +}; +use dep::types::{ + constants::{NUM_FIELDS_PER_SHA256, NUM_MSGS_PER_BASE_PARITY}, + merkle_tree::MerkleTree, + mocked::AggregationObject, + utils::uint256::U256, +}; + +struct BaseParityInputs { + msgs: [Field; NUM_MSGS_PER_BASE_PARITY], +} + +impl BaseParityInputs { + pub fn base_parity_circuit(self) -> ParityPublicInputs { + // TODO: nuke this hack once we truncate the sha256 in the frontier tree + let mut converted_msgs = [[0; NUM_FIELDS_PER_SHA256]; NUM_MSGS_PER_BASE_PARITY]; + for i in 0..NUM_MSGS_PER_BASE_PARITY { + let bytes = self.msgs[i].to_be_bytes(32); + let mut result = [0; 32]; + for i in 0..32 { + result[i] = bytes[i]; + } + let msg_as_u256 = U256::from_bytes32(result); + converted_msgs[i] = msg_as_u256.to_u128_limbs(); + } + + let sha_tree = Sha256MerkleTree::new(converted_msgs); + let pedersen_tree = MerkleTree::new(self.msgs); + + ParityPublicInputs { + aggregation_object: AggregationObject {}, + sha_root: sha_tree.get_root(), + converted_root: pedersen_tree.get_root(), + } + } +} + +#[test] +fn test_sha_root_matches_frontier_tree() { + let msgs = [ + 0x151de48ca3efbae39f180fe00b8f472ec9f25be10b4f283a87c6d78393537039, + 0x14c2ea9dedf77698d4afe23bc663263eed0bf9aa3a8b17d9b74812f185610f9e, + 0x1570cc6641699e3ae87fa258d80a6d853f7b8ccb211dc244d017e2ca6530f8a1, + 0x2806c860af67e9cd50000378411b8c4c4db172ceb2daa862b259b689ccbdc1e0 + ]; + + let base_parity_inputs = BaseParityInputs { msgs }; + let public_inputs = base_parity_inputs.base_parity_circuit(); + + // 0xb3a3fc1968999f2c2d798b900bdf0de41311be2a4d20496a7e792a521fc8abac converted to 2 fields + let expected_sha_root = [ + 0x00000000000000000000000000000000b3a3fc1968999f2c2d798b900bdf0de4, + 0x000000000000000000000000000000001311be2a4d20496a7e792a521fc8abac + ]; + + assert(public_inputs.sha_root == expected_sha_root, "sha root does not match"); +} \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr new file mode 100644 index 00000000000..c4cdf2ff697 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/lib.nr @@ -0,0 +1,9 @@ +mod base; +mod root; +mod parity_public_inputs; +mod utils; + +use crate::base::base_parity_inputs::BaseParityInputs; +use crate::root::root_parity_input::RootParityInput; +use crate::root::root_parity_inputs::RootParityInputs; +use crate::parity_public_inputs::ParityPublicInputs; \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/parity_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/parity_public_inputs.nr new file mode 100644 index 00000000000..4a5587b9d13 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/parity_public_inputs.nr @@ -0,0 +1,10 @@ +use dep::types::{ + constants::NUM_FIELDS_PER_SHA256, + mocked::AggregationObject, +}; + +struct ParityPublicInputs { + aggregation_object: AggregationObject, + sha_root: [Field; NUM_FIELDS_PER_SHA256], + converted_root: Field, +} diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root.nr new file mode 100644 index 00000000000..fad5b442cd4 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root.nr @@ -0,0 +1,2 @@ +mod root_parity_input; +mod root_parity_inputs; \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr new file mode 100644 index 00000000000..bafb3dff201 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_input.nr @@ -0,0 +1,7 @@ +use dep::types::mocked::Proof; +use crate::parity_public_inputs::ParityPublicInputs; + +struct RootParityInput { + proof: Proof, + public_inputs: ParityPublicInputs, +} diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr new file mode 100644 index 00000000000..7f230332d94 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/root/root_parity_inputs.nr @@ -0,0 +1,78 @@ +use dep::types::{ + constants::NUM_FIELDS_PER_SHA256, + merkle_tree::MerkleTree, + mocked::AggregationObject, +}; +use crate::{ + parity_public_inputs::ParityPublicInputs, + root::root_parity_input::RootParityInput, + utils::sha256_merkle_tree::Sha256MerkleTree, +}; + +global NUM_BASE_PARITY_PER_ROOT_PARITY: u64 = 4; + +struct RootParityInputs { + children: [RootParityInput; NUM_BASE_PARITY_PER_ROOT_PARITY], +} + +impl RootParityInputs { + pub fn root_parity_circuit(self) -> ParityPublicInputs { + // TODO: verify proofs of inputs.children + + let mut sha_roots = [[0; NUM_FIELDS_PER_SHA256]; NUM_BASE_PARITY_PER_ROOT_PARITY]; + let mut converted_roots = [0; NUM_BASE_PARITY_PER_ROOT_PARITY]; + for i in 0..NUM_BASE_PARITY_PER_ROOT_PARITY { + sha_roots[i] = self.children[i].public_inputs.sha_root; + converted_roots[i] = self.children[i].public_inputs.converted_root; + } + + let sha_tree = Sha256MerkleTree::new(sha_roots); + let pedersen_tree = MerkleTree::new(converted_roots); + + ParityPublicInputs { + aggregation_object: AggregationObject {}, + sha_root: sha_tree.get_root(), + converted_root: pedersen_tree.get_root(), + } + } +} + +mod tests { + use crate::{ + parity_public_inputs::ParityPublicInputs, + root::{ + root_parity_input::RootParityInput, + root_parity_inputs::RootParityInputs, + } + }; + use dep::types::mocked::{AggregationObject, Proof}; + + #[test] + fn test_sha_root_matches_frontier_tree() { + let children_sha_roots = [ + [0x00000000000000000000000000000000b3a3fc1968999f2c2d798b900bdf0de4, 0x000000000000000000000000000000001311be2a4d20496a7e792a521fc8abac], + [0x0000000000000000000000000000000043f78e0ebc9633ce336a8c086064d898, 0x00000000000000000000000000000000c32fb5d7d6011f5427459c0b8d14e91f], + [0x00000000000000000000000000000000024259b6404280addcc9319bc5a32c9a, 0x000000000000000000000000000000005d56af5c93b2f941fa326064fbe9636c], + [0x0000000000000000000000000000000053042d820859d80c474d4694e03778f8, 0x00000000000000000000000000000000dc0ac88fc1c3a97b4369c1096e904ae7], + ]; + + let children = [ + RootParityInput { proof: Proof {}, public_inputs: ParityPublicInputs { aggregation_object: AggregationObject {}, sha_root: children_sha_roots[0], converted_root: 0 } }, + RootParityInput { proof: Proof {}, public_inputs: ParityPublicInputs { aggregation_object: AggregationObject {}, sha_root: children_sha_roots[1], converted_root: 0 } }, + RootParityInput { proof: Proof {}, public_inputs: ParityPublicInputs { aggregation_object: AggregationObject {}, sha_root: children_sha_roots[2], converted_root: 0 } }, + RootParityInput { proof: Proof {}, public_inputs: ParityPublicInputs { aggregation_object: AggregationObject {}, sha_root: children_sha_roots[3], converted_root: 0 } }, + ]; + + let root_parity_inputs = RootParityInputs { children }; + + let public_inputs = root_parity_inputs.root_parity_circuit(); + + // 8e7d8bf0ef7ebd1607cc7ff9f2fbacf4574ee5b692a5a5ac1e7b1594067b9049 converted to 2 fields + let expected_sha_root = [ + 0x000000000000000000000000000000008e7d8bf0ef7ebd1607cc7ff9f2fbacf4, + 0x00000000000000000000000000000000574ee5b692a5a5ac1e7b1594067b9049 + ]; + + assert(public_inputs.sha_root == expected_sha_root, "sha root does not match"); + } +} \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr new file mode 100644 index 00000000000..2d74cfe73d5 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils.nr @@ -0,0 +1 @@ +mod sha256_merkle_tree; \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr new file mode 100644 index 00000000000..12f5e85e448 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-lib/src/utils/sha256_merkle_tree.nr @@ -0,0 +1,51 @@ +use dep::types::{ + constants::NUM_FIELDS_PER_SHA256, + hash::accumulate_sha256, +}; + +// Note: Once we'll truncate sha256 to 1 Field we can nuke this and generalize the standard MerkleTree over different +// hash functions. +struct Sha256MerkleTree { + leaves: [[Field; NUM_FIELDS_PER_SHA256]; N], + nodes: [[Field; NUM_FIELDS_PER_SHA256]; N], +} + +impl Sha256MerkleTree { + pub fn new(leaves: [[Field; NUM_FIELDS_PER_SHA256]; N]) -> Self { + let mut nodes = [[0; NUM_FIELDS_PER_SHA256]; N]; + + // We need one less node than leaves, but we cannot have computed array lengths + let total_nodes = N - 1; + let half_size = N / 2; + + // hash base layer + for i in 0..half_size { + nodes[i] = accumulate_sha256( + [ + U128::from_integer(leaves[2*i][0]), + U128::from_integer(leaves[2*i][1]), + U128::from_integer(leaves[2*i+1][0]), + U128::from_integer(leaves[2*i+1][1]) + ] + ); + } + + // hash the other layers + for i in 0..(total_nodes - half_size) { + nodes[half_size+i] = accumulate_sha256( + [ + U128::from_integer(nodes[2*i][0]), + U128::from_integer(nodes[2*i][1]), + U128::from_integer(nodes[2*i+1][0]), + U128::from_integer(nodes[2*i+1][1]) + ] + ); + } + + Sha256MerkleTree { leaves, nodes } + } + + fn get_root(self) -> [Field; NUM_FIELDS_PER_SHA256] { + self.nodes[N - 2] + } +} \ No newline at end of file diff --git a/noir-projects/noir-protocol-circuits/crates/parity-root/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/parity-root/Nargo.toml new file mode 100644 index 00000000000..7333bf020af --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-root/Nargo.toml @@ -0,0 +1,9 @@ +[package] +name = "parity_root" +type = "bin" +authors = [""] +compiler_version = ">=0.18.0" + +[dependencies] +parity_lib = { path = "../parity-lib" } +types = { path = "../types" } diff --git a/noir-projects/noir-protocol-circuits/crates/parity-root/src/main.nr b/noir-projects/noir-protocol-circuits/crates/parity-root/src/main.nr new file mode 100644 index 00000000000..11125777b66 --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/parity-root/src/main.nr @@ -0,0 +1,5 @@ +use dep::parity_lib::{RootParityInputs, ParityPublicInputs}; + +fn main(inputs: RootParityInputs) -> pub ParityPublicInputs { + inputs.root_parity_circuit() +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml index 0a1dcaa0012..9f7956eb265 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/Nargo.toml @@ -6,3 +6,4 @@ compiler_version = ">=0.18.0" [dependencies] types = { path = "../types" } +parity_lib = { path = "../parity-lib" } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr index 508e4d9ed44..e9809b19c81 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_inputs.nr @@ -2,7 +2,9 @@ use crate::{ abis::{previous_rollup_data::PreviousRollupData, constant_rollup_data::ConstantRollupData}, components, root::{compute_messages_hash, root_rollup_public_inputs::RootRollupPublicInputs} }; -use dep::types::{ +use dep::{ + parity_lib::RootParityInput, + types::{ abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, nullifier_leaf_preimage::NullifierLeafPreimage}, constants::{ NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, L1_TO_L2_MSG_SUBTREE_HEIGHT, @@ -11,12 +13,15 @@ use dep::types::{ header::Header, content_commitment::ContentCommitment, merkle_tree::{append_only_tree, calculate_subtree_root, calculate_empty_tree_root}, state_reference::StateReference +} }; struct RootRollupInputs { // All below are shared between the base and merge rollups previous_rollup_data : [PreviousRollupData; 2], + l1_to_l2_roots: RootParityInput, + // inputs required to process l1 to l2 messages new_l1_to_l2_messages : [Field; NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP], new_l1_to_l2_message_tree_root_sibling_path : [Field; L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH], @@ -44,6 +49,7 @@ impl RootRollupInputs { let l1_to_l2_subtree_root = calculate_subtree_root(self.new_l1_to_l2_messages); // Insert subtree into the l1 to l2 data tree + // TODO(#4492): insert the root from l1_to_l2_roots here instead of the one from old inbox let empty_l1_to_l2_subtree_root = calculate_empty_tree_root(L1_TO_L2_MSG_SUBTREE_HEIGHT); let new_l1_to_l2_message_tree_snapshot = append_only_tree::insert_subtree_to_snapshot_tree( self.start_l1_to_l2_message_tree_snapshot, @@ -57,11 +63,10 @@ impl RootRollupInputs { let state = StateReference { l1_to_l2_message_tree: new_l1_to_l2_message_tree_snapshot, partial: right.end }; - // TODO: in_hash: #4633 and out_hash: #4561 let content_commitment = ContentCommitment { tx_tree_height: right.height_in_block_tree + 1, txs_effects_hash: components::compute_txs_effects_hash(self.previous_rollup_data), - in_hash: [0, 0], + in_hash: self.l1_to_l2_roots.public_inputs.sha_root, out_hash: components::compute_out_hash(self.previous_rollup_data) }; 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 5bcc478692b..51d114115ca 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -184,6 +184,9 @@ global CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP: Field = 64; global CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED: Field = 52; global L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP: Field = 64; global LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP: Field = 64; +global NUM_MSGS_PER_BASE_PARITY: u64 = 4; +// NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP / NUM_MSGS_PER_BASE_PARITY +global NUM_BASE_PARITY_PER_ROOT_PARITY: u64 = 4; /** * Enumerate the hash_indices which are used for pedersen hashing. diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index 258c68db0e9..c8210f0f632 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -579,7 +579,7 @@ export class Archiver implements ArchiveSource { * @param blockNumber - L2 block number to get messages for. * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). */ - getNewL1ToL2Messages(blockNumber: bigint): Promise { + getNewL1ToL2Messages(blockNumber: bigint): Promise { return this.store.getNewL1ToL2Messages(blockNumber); } diff --git a/yarn-project/archiver/src/archiver/archiver_store.ts b/yarn-project/archiver/src/archiver/archiver_store.ts index f39399bd663..23310be7e03 100644 --- a/yarn-project/archiver/src/archiver/archiver_store.ts +++ b/yarn-project/archiver/src/archiver/archiver_store.ts @@ -146,7 +146,7 @@ export interface ArchiverDataStore { * @param blockNumber - L2 block number to get messages for. * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). */ - getNewL1ToL2Messages(blockNumber: bigint): Promise; + getNewL1ToL2Messages(blockNumber: bigint): Promise; /** * Gets up to `limit` amount of logs starting from `from`. diff --git a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts index 94649a9009f..9c6117c90a3 100644 --- a/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts +++ b/yarn-project/archiver/src/archiver/archiver_store_test_suite.ts @@ -120,7 +120,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch }); }); it('returns the L1 block number that most recently added messages from new inbox', async () => { - await store.addNewL1ToL2Messages([new NewInboxLeaf(0n, 0n, Buffer.alloc(32))], 1n); + await store.addNewL1ToL2Messages([new NewInboxLeaf(0n, 0n, Fr.ZERO)], 1n); await expect(store.getL1BlockNumber()).resolves.toEqual({ addedBlock: 0n, addedMessages: 0n, @@ -228,7 +228,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const l1ToL2MessageSubtreeSize = 2 ** L1_TO_L2_MSG_SUBTREE_HEIGHT; const generateBlockMessages = (blockNumber: bigint, numMessages: number) => - Array.from({ length: numMessages }, (_, i) => new NewInboxLeaf(blockNumber, BigInt(i), randomBytes(32))); + Array.from({ length: numMessages }, (_, i) => new NewInboxLeaf(blockNumber, BigInt(i), Fr.random())); it('returns messages in correct order', async () => { const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize); @@ -244,7 +244,7 @@ export function describeArchiverDataStore(testName: string, getStore: () => Arch const msgs = generateBlockMessages(l2BlockNumber, l1ToL2MessageSubtreeSize - 1); // We replace a message with index 4 with a message with index at the end of the tree // --> with that there will be a gap and it will be impossible to sequence the messages - msgs[4] = new NewInboxLeaf(l2BlockNumber, BigInt(l1ToL2MessageSubtreeSize - 1), randomBytes(32)); + msgs[4] = new NewInboxLeaf(l2BlockNumber, BigInt(l1ToL2MessageSubtreeSize - 1), Fr.random()); await store.addNewL1ToL2Messages(msgs, 100n); await expect(async () => { diff --git a/yarn-project/archiver/src/archiver/eth_log_handlers.ts b/yarn-project/archiver/src/archiver/eth_log_handlers.ts index 2d2e2e4a325..3dfac303a04 100644 --- a/yarn-project/archiver/src/archiver/eth_log_handlers.ts +++ b/yarn-project/archiver/src/archiver/eth_log_handlers.ts @@ -19,7 +19,7 @@ export function processLeafInsertedLogs( const leaves: NewInboxLeaf[] = []; for (const log of logs) { const { blockNumber, index, value } = log.args; - leaves.push(new NewInboxLeaf(blockNumber, index, Buffer.from(hexToBytes(value)))); + leaves.push(new NewInboxLeaf(blockNumber, index, Fr.fromString(value))); } return leaves; } diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts index 477c0692926..50a5e8c207b 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/kv_archiver_store.ts @@ -216,7 +216,7 @@ export class KVArchiverDataStore implements ArchiverDataStore { * @param blockNumber - L2 block number to get messages for. * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). */ - getNewL1ToL2Messages(blockNumber: bigint): Promise { + getNewL1ToL2Messages(blockNumber: bigint): Promise { try { return Promise.resolve(this.#messageStore.getNewL1ToL2Messages(blockNumber)); } catch (err) { diff --git a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts index a56dd2c3050..1de475fbc8e 100644 --- a/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts +++ b/yarn-project/archiver/src/archiver/kv_archiver_store/message_store.ts @@ -73,7 +73,7 @@ export class MessageStore { throw new Error(`Message index ${message.index} out of subtree range`); } const key = `${message.blockNumber}-${message.index}`; - void this.#newMessages.setIfNotExists(key, message.leaf); + void this.#newMessages.setIfNotExists(key, message.leaf.toBuffer()); } return true; @@ -208,8 +208,8 @@ export class MessageStore { return entryKeys; } - getNewL1ToL2Messages(blockNumber: bigint): Buffer[] { - const messages: Buffer[] = []; + getNewL1ToL2Messages(blockNumber: bigint): Fr[] { + const messages: Fr[] = []; let undefinedMessageFound = false; for (let messageIndex = 0; messageIndex < this.#l1ToL2MessagesSubtreeSize; messageIndex++) { // This is inefficient but probably fine for now. @@ -219,7 +219,7 @@ export class MessageStore { if (undefinedMessageFound) { throw new Error(`L1 to L2 message gap found in block ${blockNumber}`); } - messages.push(message); + messages.push(Fr.fromBuffer(message)); } else { undefinedMessageFound = true; // We continue iterating over messages here to verify that there are no more messages after the undefined one. diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts index 55ba69acfa0..ae987fe9e4e 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts @@ -12,7 +12,7 @@ export class NewL1ToL2MessageStore { * A map containing the entry key to the corresponding L1 to L2 * messages (and the number of times the message has been seen). */ - protected store: Map = new Map(); + protected store: Map = new Map(); #l1ToL2MessagesSubtreeSize = 2 ** L1_TO_L2_MSG_SUBTREE_HEIGHT; @@ -26,8 +26,8 @@ export class NewL1ToL2MessageStore { this.store.set(key, message.leaf); } - getMessages(blockNumber: bigint): Buffer[] { - const messages: Buffer[] = []; + getMessages(blockNumber: bigint): Fr[] { + const messages: Fr[] = []; let undefinedMessageFound = false; for (let messageIndex = 0; messageIndex < this.#l1ToL2MessagesSubtreeSize; messageIndex++) { // This is inefficient but probably fine for now. diff --git a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts index 444db95ff7e..d6c4387fda5 100644 --- a/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts +++ b/yarn-project/archiver/src/archiver/memory_archiver_store/memory_archiver_store.ts @@ -348,7 +348,7 @@ export class MemoryArchiverStore implements ArchiverDataStore { * @param blockNumber - L2 block number to get messages for. * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). */ - getNewL1ToL2Messages(blockNumber: bigint): Promise { + getNewL1ToL2Messages(blockNumber: bigint): Promise { return Promise.resolve(this.newL1ToL2Messages.getMessages(blockNumber)); } diff --git a/yarn-project/circuit-types/src/l1_to_l2_message.ts b/yarn-project/circuit-types/src/l1_to_l2_message.ts index 035d1ed5808..af3854998e5 100644 --- a/yarn-project/circuit-types/src/l1_to_l2_message.ts +++ b/yarn-project/circuit-types/src/l1_to_l2_message.ts @@ -9,6 +9,13 @@ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; * Interface of classes allowing for the retrieval of L1 to L2 messages. */ export interface L1ToL2MessageSource { + /** + * Gets new L1 to L2 message (to be) included in a given block. + * @param blockNumber - L2 block number to get messages for. + * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found). + */ + getNewL1ToL2Messages(blockNumber: bigint): Promise; + /** * Gets up to `limit` amount of pending L1 to L2 messages, sorted by fee * @param limit - The maximum number of messages to return (by default NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP). @@ -38,22 +45,18 @@ export class NewInboxLeaf { /** Index of the leaf in L2 block message subtree. */ public readonly index: bigint, /** Leaf of the subtree. */ - public readonly leaf: Buffer, - ) { - if (leaf.length !== 32) { - throw new Error('Invalid leaf length'); - } - } + public readonly leaf: Fr, + ) {} toBuffer(): Buffer { - return Buffer.concat([toBufferBE(this.blockNumber, 32), toBufferBE(this.index, 32), this.leaf]); + return serializeToBuffer([this.blockNumber, this.index, this.leaf]); } fromBuffer(buffer: Buffer | BufferReader): NewInboxLeaf { const reader = BufferReader.asReader(buffer); const blockNumber = toBigIntBE(reader.readBytes(32)); const index = toBigIntBE(reader.readBytes(32)); - const leaf = reader.readBytes(32); + const leaf = reader.readObject(Fr); return new NewInboxLeaf(blockNumber, index, leaf); } } diff --git a/yarn-project/circuit-types/src/stats/stats.ts b/yarn-project/circuit-types/src/stats/stats.ts index 102fb6c6a78..b08b7b50ae1 100644 --- a/yarn-project/circuit-types/src/stats/stats.ts +++ b/yarn-project/circuit-types/src/stats/stats.ts @@ -54,6 +54,8 @@ export type CircuitSimulationStats = { eventName: 'circuit-simulation'; /** Name of the circuit. */ circuitName: + | 'base-parity' + | 'root-parity' | 'base-rollup' | 'private-kernel-init' | 'private-kernel-ordering' diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index b64f8891965..866d0ab9fd9 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -115,6 +115,8 @@ export const CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP = 64; export const CONTRACT_DATA_NUM_BYTES_PER_BASE_ROLLUP_UNPADDED = 52; export const L2_TO_L1_MSGS_NUM_BYTES_PER_BASE_ROLLUP = 64; export const LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 64; +export const NUM_MSGS_PER_BASE_PARITY = 4; +export const NUM_BASE_PARITY_PER_ROOT_PARITY = 4; export enum GeneratorIndex { NOTE_HASH = 1, NOTE_HASH_NONCE = 2, diff --git a/yarn-project/circuits.js/src/structs/index.ts b/yarn-project/circuits.js/src/structs/index.ts index 2a1b8079c16..da968429df4 100644 --- a/yarn-project/circuits.js/src/structs/index.ts +++ b/yarn-project/circuits.js/src/structs/index.ts @@ -27,6 +27,10 @@ export * from './kernel/public_kernel_data.js'; export * from './kernel/public_kernel_tail_circuit_private_inputs.js'; export * from './kernel/rollup_kernel_circuit_public_inputs.js'; export * from './kernel/rollup_kernel_data.js'; +export * from './parity/base_parity_inputs.js'; +export * from './parity/parity_public_inputs.js'; +export * from './parity/root_parity_input.js'; +export * from './parity/root_parity_inputs.js'; export * from './l2_to_l1_message.js'; export * from './membership_witness.js'; export * from './nullifier_key_validation_request.js'; diff --git a/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.test.ts b/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.test.ts new file mode 100644 index 00000000000..8631ac2b2b0 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.test.ts @@ -0,0 +1,11 @@ +import { makeBaseParityInputs } from '../../tests/factories.js'; +import { BaseParityInputs } from './base_parity_inputs.js'; + +describe('BaseParityInputs', () => { + it(`serializes a BaseParityInputs to buffer and deserializes it back`, () => { + const expected = makeBaseParityInputs(); + const buffer = expected.toBuffer(); + const res = BaseParityInputs.fromBuffer(buffer); + expect(res).toEqual(expected); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts b/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts new file mode 100644 index 00000000000..c369424cdc0 --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/base_parity_inputs.ts @@ -0,0 +1,30 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, NUM_MSGS_PER_BASE_PARITY } from '../../constants.gen.js'; + +export class BaseParityInputs { + constructor( + /** Aggregated proof of all the parity circuit iterations. */ + public readonly msgs: Tuple, + ) {} + + public static fromSlice( + array: Tuple, + index: number, + ): BaseParityInputs { + const start = index * NUM_MSGS_PER_BASE_PARITY; + const end = start + NUM_MSGS_PER_BASE_PARITY; + const msgs = array.slice(start, end); + return new BaseParityInputs(msgs as Tuple); + } + + toBuffer() { + return serializeToBuffer(this.msgs); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new BaseParityInputs(reader.readArray(NUM_MSGS_PER_BASE_PARITY, Fr)); + } +} diff --git a/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.test.ts new file mode 100644 index 00000000000..f4ea958145f --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.test.ts @@ -0,0 +1,11 @@ +import { makeParityPublicInputs } from '../../tests/factories.js'; +import { ParityPublicInputs } from './parity_public_inputs.js'; + +describe('ParityPublicInputs', () => { + it(`serializes a ParityPublicInputs to buffer and deserializes it back`, () => { + const expected = makeParityPublicInputs(); + const buffer = expected.toBuffer(); + const res = ParityPublicInputs.fromBuffer(buffer); + expect(res).toEqual(expected); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts b/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts new file mode 100644 index 00000000000..7f70c6239ef --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/parity_public_inputs.ts @@ -0,0 +1,37 @@ +import { Fr } from '@aztec/foundation/fields'; +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { FieldsOf } from '@aztec/foundation/types'; + +import { AggregationObject } from '../aggregation_object.js'; + +export class ParityPublicInputs { + constructor( + /** Aggregated proof of all the parity circuit iterations. */ + public aggregationObject: AggregationObject, + /** Root of the SHA256 tree. */ + public shaRoot: Buffer, + /** Root of the converted tree. */ + public convertedRoot: Fr, + ) { + if (shaRoot.length !== 32) { + throw new Error(`shaRoot buffer must be 32 bytes. Got ${shaRoot.length} bytes`); + } + } + + toBuffer() { + return serializeToBuffer(...ParityPublicInputs.getFields(this)); + } + + static from(fields: FieldsOf): ParityPublicInputs { + return new ParityPublicInputs(...ParityPublicInputs.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.aggregationObject, fields.shaRoot, fields.convertedRoot] as const; + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new ParityPublicInputs(reader.readObject(AggregationObject), reader.readBytes(32), reader.readObject(Fr)); + } +} diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_input.test.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_input.test.ts new file mode 100644 index 00000000000..1dd76321e0c --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_input.test.ts @@ -0,0 +1,11 @@ +import { makeRootParityInput } from '../../tests/factories.js'; +import { RootParityInput } from './root_parity_input.js'; + +describe('RootParityInput', () => { + it(`serializes a RootParityInput to buffer and deserializes it back`, () => { + const expected = makeRootParityInput(); + const buffer = expected.toBuffer(); + const res = RootParityInput.fromBuffer(buffer); + expect(res).toEqual(expected); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts new file mode 100644 index 00000000000..1c55e5c83bb --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_input.ts @@ -0,0 +1,31 @@ +import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; +import { FieldsOf } from '@aztec/foundation/types'; + +import { Proof } from '../proof.js'; +import { ParityPublicInputs } from './parity_public_inputs.js'; + +export class RootParityInput { + constructor( + /** The proof of the execution of the parity circuit. */ + public readonly proof: Proof, + /** The public inputs of the parity circuit. */ + public readonly publicInputs: ParityPublicInputs, + ) {} + + toBuffer() { + return serializeToBuffer(...RootParityInput.getFields(this)); + } + + static from(fields: FieldsOf): RootParityInput { + return new RootParityInput(...RootParityInput.getFields(fields)); + } + + static getFields(fields: FieldsOf) { + return [fields.proof, fields.publicInputs] as const; + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new RootParityInput(reader.readObject(Proof), reader.readObject(ParityPublicInputs)); + } +} diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.test.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.test.ts new file mode 100644 index 00000000000..97c28baa9fc --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.test.ts @@ -0,0 +1,11 @@ +import { makeRootParityInputs } from '../../tests/factories.js'; +import { RootParityInputs } from './root_parity_inputs.js'; + +describe('RootParityInputs', () => { + it(`serializes a RootParityInputs to buffer and deserializes it back`, () => { + const expected = makeRootParityInputs(); + const buffer = expected.toBuffer(); + const res = RootParityInputs.fromBuffer(buffer); + expect(res).toEqual(expected); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts b/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts new file mode 100644 index 00000000000..4a73162a6af --- /dev/null +++ b/yarn-project/circuits.js/src/structs/parity/root_parity_inputs.ts @@ -0,0 +1,20 @@ +import { BufferReader, Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; + +import { NUM_BASE_PARITY_PER_ROOT_PARITY } from '../../constants.gen.js'; +import { RootParityInput } from './root_parity_input.js'; + +export class RootParityInputs { + constructor( + /** Public inputs of children and their proofs. */ + public readonly children: Tuple, + ) {} + + toBuffer() { + return serializeToBuffer(this.children); + } + + static fromBuffer(buffer: Buffer | BufferReader) { + const reader = BufferReader.asReader(buffer); + return new RootParityInputs(reader.readArray(NUM_BASE_PARITY_PER_ROOT_PARITY, RootParityInput)); + } +} diff --git a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts index 2a839e6eda6..c2a88501eb7 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -10,6 +10,7 @@ import { } from '../../constants.gen.js'; import { AggregationObject } from '../aggregation_object.js'; import { Header } from '../header.js'; +import { RootParityInput } from '../parity/root_parity_input.js'; import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; import { PreviousRollupData } from './previous_rollup_data.js'; @@ -24,6 +25,10 @@ export class RootRollupInputs { * from 2 merge or base rollup circuits. */ public previousRollupData: [PreviousRollupData, PreviousRollupData], + /** + * The original and converted roots of the L1 to L2 messages subtrees. + */ + public l1ToL2Roots: RootParityInput, /** * New L1 to L2 messages. */ @@ -57,6 +62,7 @@ export class RootRollupInputs { static getFields(fields: FieldsOf) { return [ fields.previousRollupData, + fields.l1ToL2Roots, fields.newL1ToL2Messages, fields.newL1ToL2MessageTreeRootSiblingPath, fields.startL1ToL2MessageTreeSnapshot, diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index bf620a8c1c0..f404049880e 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -12,6 +12,7 @@ import { AggregationObject, AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, CallContext, CallRequest, @@ -71,13 +72,16 @@ import { NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + NUM_BASE_PARITY_PER_ROOT_PARITY, NUM_FIELDS_PER_SHA256, + NUM_MSGS_PER_BASE_PARITY, NoteHashReadRequestMembershipWitness, NullifierKeyValidationRequest, NullifierKeyValidationRequestContext, NullifierLeafPreimage, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, PUBLIC_DATA_TREE_HEIGHT, + ParityPublicInputs, PartialStateReference, Point, PreviousRollupData, @@ -108,6 +112,8 @@ import { ReadRequest, ReadRequestContext, RollupTypes, + RootParityInput, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, SideEffect, @@ -1026,6 +1032,7 @@ export function makePreviousRollupData( export function makeRootRollupInputs(seed = 0, globalVariables?: GlobalVariables): RootRollupInputs { return new RootRollupInputs( [makePreviousRollupData(seed, globalVariables), makePreviousRollupData(seed + 0x1000, globalVariables)], + makeRootParityInput(seed + 0x2000), makeTuple(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, fr, 0x2100), makeTuple(L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, fr, 0x2100), makeAppendOnlyTreeSnapshot(seed + 0x2200), @@ -1034,6 +1041,26 @@ export function makeRootRollupInputs(seed = 0, globalVariables?: GlobalVariables ); } +export function makeRootParityInput(seed = 0): RootParityInput { + return new RootParityInput(makeProof(seed), makeParityPublicInputs(seed + 0x100)); +} + +export function makeParityPublicInputs(seed = 0): ParityPublicInputs { + return new ParityPublicInputs( + makeAggregationObject(seed), + toBufferBE(BigInt(seed + 0x200), 32), + new Fr(BigInt(seed + 0x300)), + ); +} + +export function makeBaseParityInputs(seed = 0): BaseParityInputs { + return new BaseParityInputs(makeTuple(NUM_MSGS_PER_BASE_PARITY, fr, seed + 0x3000)); +} + +export function makeRootParityInputs(seed = 0): RootParityInputs { + return new RootParityInputs(makeTuple(NUM_BASE_PARITY_PER_ROOT_PARITY, makeRootParityInput, seed + 0x4000)); +} + /** * Makes root rollup public inputs. * @param seed - The seed to use for generating the root rollup public inputs. diff --git a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts index 994f829115f..608dbb1da33 100644 --- a/yarn-project/end-to-end/src/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/integration_l1_publisher.test.ts @@ -27,7 +27,7 @@ import { fr, makeNewSideEffect, makeNewSideEffectLinkedToNoteHash, makeProof } f import { createEthereumChain } from '@aztec/ethereum'; import { makeTuple, range } from '@aztec/foundation/array'; import { openTmpStore } from '@aztec/kv-store/utils'; -import { AvailabilityOracleAbi, InboxAbi, OutboxAbi, RollupAbi } from '@aztec/l1-artifacts'; +import { AvailabilityOracleAbi, InboxAbi, NewInboxAbi, OutboxAbi, RollupAbi } from '@aztec/l1-artifacts'; import { EmptyRollupProver, L1Publisher, @@ -80,6 +80,7 @@ describe('L1Publisher integration', () => { let rollup: GetContractReturnType>; let inbox: GetContractReturnType>; + let newInbox: GetContractReturnType>; let outbox: GetContractReturnType>; let publisher: L1Publisher; @@ -123,6 +124,12 @@ describe('L1Publisher integration', () => { abi: InboxAbi, client: walletClient, }); + const newInboxAddress = await rollup.read.NEW_INBOX(); + newInbox = getContract({ + address: newInboxAddress, + abi: NewInboxAbi, + client: walletClient, + }); outbox = getContract({ address: outboxAddress, abi: OutboxAbi, @@ -196,6 +203,12 @@ describe('L1Publisher integration', () => { // Using the 0 value for the secretHash. const emptySecretHash = Fr.ZERO.toString(); + await newInbox.write.sendL2Message( + [{ actor: recipient.recipient.toString(), version: BigInt(recipient.version) }, contentString, emptySecretHash], + {} as any, + ); + + // TODO(#4492): Nuke this when purging the old inbox await inbox.write.sendL2Message( [ { actor: recipient.recipient.toString(), version: BigInt(recipient.version) }, @@ -347,6 +360,8 @@ describe('L1Publisher integration', () => { '0x1647b194c649f5dd01d7c832f89b0f496043c9150797923ea89e93d5ac619a93', ); + let newModelL1ToL2Messages: Fr[] = []; + for (let i = 0; i < numberOfConsecutiveBlocks; i++) { const l1ToL2Content = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 128 * i + 1 + 0x400).map(fr); const l1ToL2Messages: Fr[] = []; @@ -394,7 +409,7 @@ describe('L1Publisher integration', () => { coinbase, feeRecipient, ); - const [block] = await builder.buildL2Block(globalVariables, txs, l1ToL2Messages); + const [block] = await builder.buildL2Block(globalVariables, txs, newModelL1ToL2Messages, l1ToL2Messages); prevHeader = block.header; // check that values are in the inbox @@ -455,6 +470,9 @@ describe('L1Publisher integration', () => { for (let j = 0; j < newL2ToL1MsgsArray.length; j++) { expect(await outbox.read.contains([newL2ToL1MsgsArray[j].toString()])).toBeTruthy(); } + + // There is a 1 block lag in the new model + newModelL1ToL2Messages = l1ToL2Messages; } }, 360_000); @@ -476,7 +494,7 @@ describe('L1Publisher integration', () => { coinbase, feeRecipient, ); - const [block] = await builder.buildL2Block(globalVariables, txs, l1ToL2Messages); + const [block] = await builder.buildL2Block(globalVariables, txs, l1ToL2Messages, l1ToL2Messages); prevHeader = block.header; writeJson(`empty_block_${i}`, block, l1ToL2Messages, [], AztecAddress.ZERO, deployerAccount.address); diff --git a/yarn-project/foundation/src/serialize/serialize.ts b/yarn-project/foundation/src/serialize/serialize.ts index 77785e8f27d..9023fc56598 100644 --- a/yarn-project/foundation/src/serialize/serialize.ts +++ b/yarn-project/foundation/src/serialize/serialize.ts @@ -110,6 +110,7 @@ export type Bufferable = | boolean | Buffer | number + | bigint | string | { /** @@ -149,6 +150,12 @@ export function serializeToBufferArray(...objs: Bufferable[]): Buffer[] { ret.push(obj); } else if (typeof obj === 'boolean') { ret.push(boolToBuffer(obj)); + } else if (typeof obj === 'bigint') { + // Throw if bigint does not fit into 32 bytes + if (obj > BigInt('0xffffffffffffffffffffffffffffffff')) { + throw new Error(`BigInt ${obj} does not fit into 32 bytes`); + } + ret.push(serializeBigInt(obj)); } else if (typeof obj === 'number') { // Note: barretenberg assumes everything is big-endian ret.push(numToUInt32BE(obj)); // TODO: Are we always passing numbers as UInt32? diff --git a/yarn-project/noir-protocol-circuits-types/src/index.ts b/yarn-project/noir-protocol-circuits-types/src/index.ts index 6a414362532..cf56cc0b7c1 100644 --- a/yarn-project/noir-protocol-circuits-types/src/index.ts +++ b/yarn-project/noir-protocol-circuits-types/src/index.ts @@ -1,7 +1,9 @@ import { BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, MergeRollupInputs, + ParityPublicInputs, PrivateKernelInitCircuitPrivateInputs, PrivateKernelInnerCircuitPrivateInputs, PrivateKernelInnerCircuitPublicInputs, @@ -10,6 +12,7 @@ import { PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, } from '@aztec/circuits.js'; @@ -19,6 +22,8 @@ import { WasmBlackBoxFunctionSolver, createBlackBoxSolver, executeCircuitWithBla import { Abi, abiDecode, abiEncode } from '@noir-lang/noirc_abi'; import { WitnessMap } from '@noir-lang/types'; +import BaseParityJson from './target/parity_base.json' assert { type: 'json' }; +import RootParityJson from './target/parity_root.json' assert { type: 'json' }; import PrivateKernelInitJson from './target/private_kernel_init.json' assert { type: 'json' }; import PrivateKernelInitSimulatedJson from './target/private_kernel_init_simulated.json' assert { type: 'json' }; import PrivateKernelInnerJson from './target/private_kernel_inner.json' assert { type: 'json' }; @@ -34,8 +39,10 @@ import MergeRollupJson from './target/rollup_merge.json' assert { type: 'json' } import RootRollupJson from './target/rollup_root.json' assert { type: 'json' }; import { mapBaseOrMergeRollupPublicInputsFromNoir, + mapBaseParityInputsToNoir, mapBaseRollupInputsToNoir, mapMergeRollupInputsToNoir, + mapParityPublicInputsFromNoir, mapPrivateKernelInitCircuitPrivateInputsToNoir, mapPrivateKernelInnerCircuitPrivateInputsToNoir, mapPrivateKernelInnerCircuitPublicInputsFromNoir, @@ -44,9 +51,12 @@ import { mapPublicKernelCircuitPrivateInputsToNoir, mapPublicKernelCircuitPublicInputsFromNoir, mapPublicKernelTailCircuitPrivateInputsToNoir, + mapRootParityInputsToNoir, mapRootRollupInputsToNoir, mapRootRollupPublicInputsFromNoir, } from './type_conversion.js'; +import { ReturnType as BaseParityReturnType } from './types/parity_base_types.js'; +import { ReturnType as RootParityReturnType } from './types/parity_root_types.js'; import { InputType as InitInputType, ReturnType as InitReturnType } from './types/private_kernel_init_types.js'; import { InputType as InnerInputType, ReturnType as InnerReturnType } from './types/private_kernel_inner_types.js'; import { InputType as TailInputType, ReturnType as TailReturnType } from './types/private_kernel_tail_types.js'; @@ -85,6 +95,10 @@ export const PublicKernelTeardownArtifact = PublicKernelTeardownSimulatedJson as export const PublicKernelTailArtifact = PublicKernelTailSimulatedJson as NoirCompiledCircuit; +export const BaseParityArtifact = BaseParityJson as NoirCompiledCircuit; + +export const RootParityArtifact = RootParityJson as NoirCompiledCircuit; + export const BaseRollupArtifact = BaseRollupSimulatedJson as NoirCompiledCircuit; export const MergeRollupArtifact = MergeRollupJson as NoirCompiledCircuit; @@ -151,7 +165,29 @@ export async function executeTail( } /** - * Converts the inputs to the base rollup circuit into a witness map. + * Converts the inputs of the base parity circuit into a witness map. + * @param inputs - The base parity inputs. + * @returns The witness map + */ +export function convertBaseParityInputsToWitnessMap(inputs: BaseParityInputs): WitnessMap { + const mapped = mapBaseParityInputsToNoir(inputs); + const initialWitnessMap = abiEncode(BaseParityJson.abi as Abi, { inputs: mapped as any }); + return initialWitnessMap; +} + +/** + * Converts the inputs of the root parity circuit into a witness map. + * @param inputs - The root parity inputs. + * @returns The witness map + */ +export function convertRootParityInputsToWitnessMap(inputs: RootParityInputs): WitnessMap { + const mapped = mapRootParityInputsToNoir(inputs); + const initialWitnessMap = abiEncode(RootParityJson.abi as Abi, { inputs: mapped as any }); + return initialWitnessMap; +} + +/** + * Converts the inputs of the base rollup circuit into a witness map. * @param inputs - The base rollup inputs. * @returns The witness map */ @@ -162,7 +198,7 @@ export function convertBaseRollupInputsToWitnessMap(inputs: BaseRollupInputs): W } /** - * Converts the inputs to the merge rollup circuit into a witness map. + * Converts the inputs of the merge rollup circuit into a witness map. * @param inputs - The merge rollup inputs. * @returns The witness map */ @@ -173,7 +209,7 @@ export function convertMergeRollupInputsToWitnessMap(inputs: MergeRollupInputs): } /** - * Converts the inputs to the root rollup circuit into a witness map. + * Converts the inputs of the root rollup circuit into a witness map. * @param inputs - The root rollup inputs. * @returns The witness map */ @@ -183,7 +219,7 @@ export function convertRootRollupInputsToWitnessMap(inputs: RootRollupInputs): W return initialWitnessMap; } /** - * Converts the inputs to the public setup circuit into a witness map + * Converts the inputs of the public setup circuit into a witness map * @param inputs - The public kernel inputs. * @returns The witness map */ @@ -194,7 +230,7 @@ export function convertPublicSetupRollupInputsToWitnessMap(inputs: PublicKernelC } /** - * Converts the inputs to the public setup circuit into a witness map + * Converts the inputs of the public setup circuit into a witness map * @param inputs - The public kernel inputs. * @returns The witness map */ @@ -205,7 +241,7 @@ export function convertPublicInnerRollupInputsToWitnessMap(inputs: PublicKernelC } /** - * Converts the inputs to the public teardown circuit into a witness map + * Converts the inputs of the public teardown circuit into a witness map * @param inputs - The public kernel inputs. * @returns The witness map */ @@ -216,7 +252,7 @@ export function convertPublicTeardownRollupInputsToWitnessMap(inputs: PublicKern } /** - * Converts the inputs to the public tail circuit into a witness map + * Converts the inputs of the public tail circuit into a witness map * @param inputs - The public kernel inputs. * @returns The witness map */ @@ -227,7 +263,7 @@ export function convertPublicTailInputsToWitnessMap(inputs: PublicKernelTailCirc } /** - * Converts the outputs to the base rollup circuit. + * Converts the outputs of the base rollup circuit from a witness map. * @param outputs - The base rollup outputs as a witness map. * @returns The public inputs. */ @@ -242,7 +278,7 @@ export function convertBaseRollupOutputsFromWitnessMap(outputs: WitnessMap): Bas } /** - * Converts the outputs to the merge rollup circuit. + * Converts the outputs of the merge rollup circuit from a witness map. * @param outputs - The merge rollup outputs as a witness map. * @returns The public inputs. */ @@ -257,7 +293,7 @@ export function convertMergeRollupOutputsFromWitnessMap(outputs: WitnessMap): Ba } /** - * Converts the outputs to the root rollup circuit. + * Converts the outputs of the root rollup circuit from a witness map. * @param outputs - The root rollup outputs as a witness map. * @returns The public inputs. */ @@ -272,7 +308,37 @@ export function convertRootRollupOutputsFromWitnessMap(outputs: WitnessMap): Roo } /** - * Converts the outputs to the public setup circuit. + * Converts the outputs of the base parity circuit from a witness map. + * @param outputs - The base parity outputs as a witness map. + * @returns The public inputs. + */ +export function convertBaseParityOutputsFromWitnessMap(outputs: WitnessMap): ParityPublicInputs { + // Decode the witness map into two fields, the return values and the inputs + const decodedInputs: DecodedInputs = abiDecode(BaseParityJson.abi as Abi, outputs); + + // Cast the inputs as the return type + const returnType = decodedInputs.return_value as BaseParityReturnType; + + return mapParityPublicInputsFromNoir(returnType); +} + +/** + * Converts the outputs of the root parity circuit from a witness map. + * @param outputs - The root parity outputs as a witness map. + * @returns The public inputs. + */ +export function convertRootParityOutputsFromWitnessMap(outputs: WitnessMap): ParityPublicInputs { + // Decode the witness map into two fields, the return values and the inputs + const decodedInputs: DecodedInputs = abiDecode(RootParityJson.abi as Abi, outputs); + + // Cast the inputs as the return type + const returnType = decodedInputs.return_value as RootParityReturnType; + + return mapParityPublicInputsFromNoir(returnType); +} + +/** + * Converts the outputs of the public setup circuit from a witness map. * @param outputs - The public kernel outputs as a witness map. * @returns The public inputs. */ @@ -287,7 +353,7 @@ export function convertPublicSetupRollupOutputFromWitnessMap(outputs: WitnessMap } /** - * Converts the outputs to the public inner circuit. + * Converts the outputs of the public inner circuit from a witness map. * @param outputs - The public kernel outputs as a witness map. * @returns The public inputs. */ @@ -302,7 +368,7 @@ export function convertPublicInnerRollupOutputFromWitnessMap(outputs: WitnessMap } /** - * Converts the outputs to the public tail circuit. + * Converts the outputs of the public tail circuit from a witness map. * @param outputs - The public kernel outputs as a witness map. * @returns The public inputs. */ @@ -317,7 +383,7 @@ export function convertPublicTeardownRollupOutputFromWitnessMap(outputs: Witness } /** - * Converts the outputs to the public tail circuit. + * Converts the outputs of the public tail circuit from a witness map. * @param outputs - The public kernel outputs as a witness map. * @returns The public inputs. */ diff --git a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts index 5821ec3446f..1854a5fd73b 100644 --- a/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts +++ b/yarn-project/noir-protocol-circuits-types/src/scripts/generate_ts_from_abi.ts @@ -198,6 +198,8 @@ function generateTsInterface(abiObj: NoirFunctionAbi): string { } const circuits = [ + 'parity_base', + 'parity_root', 'private_kernel_init', 'private_kernel_inner', 'private_kernel_tail', diff --git a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts index db04b103d6a..df54db41010 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -4,6 +4,7 @@ import { AppendOnlyTreeSnapshot, AztecAddress, BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, CallContext, CallRequest, @@ -57,6 +58,7 @@ import { NullifierNonExistentReadRequestHints, NullifierReadRequestHints, PUBLIC_DATA_TREE_HEIGHT, + ParityPublicInputs, PartialStateReference, PendingReadHint, Point, @@ -90,6 +92,8 @@ import { ReadRequestStatus, RollupKernelCircuitPublicInputs, RollupKernelData, + RootParityInput, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, SettledReadHint, @@ -102,6 +106,8 @@ import { } from '@aztec/circuits.js'; import { Tuple, from2Fields, mapTuple, to2Fields } from '@aztec/foundation/serialize'; +import { BaseParityInputs as BaseParityInputsNoir } from './types/parity_base_types.js'; +import { RootParityInputs as RootParityInputsNoir } from './types/parity_root_types.js'; import { CallContext as CallContextNoir, CallRequest as CallRequestNoir, @@ -189,8 +195,10 @@ import { FixedLengthArray, GlobalVariables as GlobalVariablesNoir, Header as HeaderNoir, + ParityPublicInputs as ParityPublicInputsNoir, PartialStateReference as PartialStateReferenceNoir, PreviousRollupData as PreviousRollupDataNoir, + RootParityInput as RootParityInputNoir, RootRollupInputs as RootRollupInputsNoir, RootRollupPublicInputs as RootRollupPublicInputsNoir, StateReference as StateReferenceNoir, @@ -1668,6 +1676,7 @@ export function mapAppendOnlyTreeSnapshotToNoir(snapshot: AppendOnlyTreeSnapshot export function mapRootRollupInputsToNoir(rootRollupInputs: RootRollupInputs): RootRollupInputsNoir { return { previous_rollup_data: mapTuple(rootRollupInputs.previousRollupData, mapPreviousRollupDataToNoir), + l1_to_l2_roots: mapRootParityInputToNoir(rootRollupInputs.l1ToL2Roots), new_l1_to_l2_messages: mapTuple(rootRollupInputs.newL1ToL2Messages, mapFieldToNoir), new_l1_to_l2_message_tree_root_sibling_path: mapTuple( rootRollupInputs.newL1ToL2MessageTreeRootSiblingPath, @@ -1681,6 +1690,21 @@ export function mapRootRollupInputsToNoir(rootRollupInputs: RootRollupInputs): R }; } +export function mapRootParityInputToNoir(rootParityInput: RootParityInput): RootParityInputNoir { + return { + proof: {}, + public_inputs: mapParityPublicInputsToNoir(rootParityInput.publicInputs), + }; +} + +export function mapParityPublicInputsToNoir(parityPublicInputs: ParityPublicInputs): ParityPublicInputsNoir { + return { + aggregation_object: {}, + sha_root: mapSha256HashToNoir(parityPublicInputs.shaRoot), + converted_root: mapFieldToNoir(parityPublicInputs.convertedRoot), + }; +} + /** * Maps a root rollup public inputs from noir. * @param rootRollupPublicInputs - The noir root rollup public inputs. @@ -1697,6 +1721,19 @@ export function mapRootRollupPublicInputsFromNoir( ); } +/** + * Maps a parity public inputs from noir. + * @param parityPublicInputs - The noir parity public inputs. + * @returns The circuits.js parity public inputs. + */ +export function mapParityPublicInputsFromNoir(parityPublicInputs: ParityPublicInputsNoir): ParityPublicInputs { + return new ParityPublicInputs( + AggregationObject.makeFake(), + mapSha256HashFromNoir(parityPublicInputs.sha_root), + mapFieldFromNoir(parityPublicInputs.converted_root), + ); +} + /** * Maps header to Noir * @param header - The header. @@ -1913,6 +1950,28 @@ export function mapStateDiffHintsToNoir(hints: StateDiffHints): StateDiffHintsNo }; } +/** + * Maps base parity inputs to noir. + * @param inputs - The circuits.js base parity inputs. + * @returns The noir base parity inputs. + */ +export function mapBaseParityInputsToNoir(inputs: BaseParityInputs): BaseParityInputsNoir { + return { + msgs: mapTuple(inputs.msgs, mapFieldToNoir), + }; +} + +/** + * Maps root parity inputs to noir. + * @param inputs - The circuits.js root parity inputs. + * @returns The noir root parity inputs. + */ +export function mapRootParityInputsToNoir(inputs: RootParityInputs): RootParityInputsNoir { + return { + children: mapTuple(inputs.children, mapRootParityInputToNoir), + }; +} + /** * Maps the inputs to the base rollup to noir. * @param input - The circuits.js base rollup inputs. diff --git a/yarn-project/sequencer-client/src/block_builder/index.ts b/yarn-project/sequencer-client/src/block_builder/index.ts index df283609c32..d4d392ae6cc 100644 --- a/yarn-project/sequencer-client/src/block_builder/index.ts +++ b/yarn-project/sequencer-client/src/block_builder/index.ts @@ -13,12 +13,14 @@ export interface BlockBuilder { * Note that the number of txs need to be a power of two. * @param globalVariables - Global variables to include in the block. * @param txs - Processed txs to include. + * @param newModelL1ToL2Messages - L1 to L2 messages emitted by the new inbox. * @param newL1ToL2Messages - L1 to L2 messages to be part of the block. * @returns The new L2 block along with its proof from the root circuit. */ buildL2Block( globalVariables: GlobalVariables, txs: ProcessedTx[], - newL1ToL2Messages: Fr[], + newModelL1ToL2Messages: Fr[], // TODO(#4492): Rename this when purging the old inbox + newL1ToL2Messages: Fr[], // TODO(#4492): Nuke this when purging the old inbox ): Promise<[L2Block, Proof]>; } diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts index 4cd73e2fa69..0a647fa0f56 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.test.ts @@ -36,6 +36,7 @@ import { makeBaseOrMergeRollupPublicInputs, makeNewSideEffect, makeNewSideEffectLinkedToNoteHash, + makeParityPublicInputs, makePrivateKernelTailCircuitPublicInputs, makeProof, makePublicCallRequest, @@ -81,7 +82,8 @@ describe('sequencer/solo_block_builder', () => { let baseRollupOutputLeft: BaseOrMergeRollupPublicInputs; let baseRollupOutputRight: BaseOrMergeRollupPublicInputs; let rootRollupOutput: RootRollupPublicInputs; - let mockL1ToL2Messages: Fr[]; + let newModelMockL1ToL2Messages: Fr[]; // TODO(#4492): Rename this when purging the old inbox + let mockL1ToL2Messages: Fr[]; // TODO(#4492): Nuke this when purging the old inbox let globalVariables: GlobalVariables; @@ -104,6 +106,7 @@ describe('sequencer/solo_block_builder', () => { builder = new SoloBlockBuilder(builderDb, vks, simulator, prover); // Create mock l1 to L2 messages + newModelMockL1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)); mockL1ToL2Messages = new Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)); // Create mock outputs for simulator @@ -113,8 +116,16 @@ describe('sequencer/solo_block_builder', () => { rootRollupOutput.header.globalVariables = globalVariables; // Set up mocks + prover.getBaseParityProof.mockResolvedValue(emptyProof); + prover.getRootParityProof.mockResolvedValue(emptyProof); prover.getBaseRollupProof.mockResolvedValue(emptyProof); prover.getRootRollupProof.mockResolvedValue(emptyProof); + simulator.baseParityCircuit + .mockResolvedValueOnce(makeParityPublicInputs(1)) + .mockResolvedValue(makeParityPublicInputs(2)) + .mockResolvedValue(makeParityPublicInputs(3)) + .mockResolvedValueOnce(makeParityPublicInputs(4)); + simulator.rootParityCircuit.mockResolvedValueOnce(makeParityPublicInputs(5)); simulator.baseRollupCircuit .mockResolvedValueOnce(baseRollupOutputLeft) .mockResolvedValueOnce(baseRollupOutputRight); @@ -274,7 +285,12 @@ describe('sequencer/solo_block_builder', () => { const txs = await buildMockSimulatorInputs(); // Actually build a block! - const [l2Block, proof] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages); + const [l2Block, proof] = await builder.buildL2Block( + globalVariables, + txs, + newModelMockL1ToL2Messages, + mockL1ToL2Messages, + ); expect(l2Block.number).toEqual(blockNumber); expect(proof).toEqual(emptyProof); @@ -284,7 +300,9 @@ describe('sequencer/solo_block_builder', () => { // Assemble a fake transaction const txs = await buildMockSimulatorInputs(); const l1ToL2Messages = new Array(100).fill(new Fr(0n)); - await expect(builder.buildL2Block(globalVariables, txs, l1ToL2Messages)).rejects.toThrow(); + await expect( + builder.buildL2Block(globalVariables, txs, newModelMockL1ToL2Messages, l1ToL2Messages), + ).rejects.toThrow(); }); }); @@ -359,7 +377,12 @@ describe('sequencer/solo_block_builder', () => { ...(await Promise.all(times(totalCount - bloatedCount, makeEmptyProcessedTx))), ]; - const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages); + const [l2Block] = await builder.buildL2Block( + globalVariables, + txs, + newModelMockL1ToL2Messages, + mockL1ToL2Messages, + ); expect(l2Block.number).toEqual(blockNumber); await updateExpectedTreesFromTxs(txs); @@ -383,7 +406,12 @@ describe('sequencer/solo_block_builder', () => { makeEmptyProcessedTx(), ]); - const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages); + const [l2Block] = await builder.buildL2Block( + globalVariables, + txs, + newModelMockL1ToL2Messages, + mockL1ToL2Messages, + ); expect(l2Block.number).toEqual(blockNumber); }, 30_000); @@ -397,7 +425,7 @@ describe('sequencer/solo_block_builder', () => { const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); - const [l2Block] = await builder.buildL2Block(globalVariables, txs, l1ToL2Messages); + const [l2Block] = await builder.buildL2Block(globalVariables, txs, newModelMockL1ToL2Messages, l1ToL2Messages); expect(l2Block.number).toEqual(blockNumber); }, 200_000); @@ -433,7 +461,12 @@ describe('sequencer/solo_block_builder', () => { NULLIFIER_SUBTREE_HEIGHT, ); - const [l2Block] = await builder.buildL2Block(globalVariables, txs, mockL1ToL2Messages); + const [l2Block] = await builder.buildL2Block( + globalVariables, + txs, + newModelMockL1ToL2Messages, + mockL1ToL2Messages, + ); expect(l2Block.number).toEqual(blockNumber); }, 20000); diff --git a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts index da3553c64a8..8332b16db23 100644 --- a/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts +++ b/yarn-project/sequencer-client/src/block_builder/solo_block_builder.ts @@ -4,6 +4,7 @@ import { ARCHIVE_HEIGHT, AppendOnlyTreeSnapshot, BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, ConstantRollupData, GlobalVariables, @@ -20,6 +21,7 @@ import { NULLIFIER_SUBTREE_SIBLING_PATH_LENGTH, NULLIFIER_TREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + NUM_BASE_PARITY_PER_ROOT_PARITY, NullifierLeafPreimage, PUBLIC_DATA_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_SIBLING_PATH_LENGTH, @@ -33,6 +35,8 @@ import { RollupKernelCircuitPublicInputs, RollupKernelData, RollupTypes, + RootParityInput, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, StateDiffHints, @@ -85,6 +89,7 @@ export class SoloBlockBuilder implements BlockBuilder { * Builds an L2 block with the given number containing the given txs, updating state trees. * @param globalVariables - Global variables to be used in the block. * @param txs - Processed transactions to include in the block. + * @param newModelL1ToL2Messages - L1 to L2 messages emitted by the new inbox. * @param newL1ToL2Messages - L1 to L2 messages to be part of the block. * @param timestamp - Timestamp of the block. * @returns The new L2 block and a correctness proof as returned by the root rollup circuit. @@ -92,13 +97,19 @@ export class SoloBlockBuilder implements BlockBuilder { public async buildL2Block( globalVariables: GlobalVariables, txs: ProcessedTx[], + newModelL1ToL2Messages: Fr[], // TODO(#4492): Rename this when purging the old inbox newL1ToL2Messages: Fr[], ): Promise<[L2Block, Proof]> { // Check txs are good for processing by checking if all the tree snapshots in header are non-empty this.validateTxs(txs); // We fill the tx batch with empty txs, we process only one tx at a time for now - const [circuitsOutput, proof] = await this.runCircuits(globalVariables, txs, newL1ToL2Messages); + const [circuitsOutput, proof] = await this.runCircuits( + globalVariables, + txs, + newModelL1ToL2Messages, + newL1ToL2Messages, + ); // Collect all new nullifiers, commitments, and contracts from all txs in this block const txEffects: TxEffect[] = txs.map(tx => toTxEffect(tx)); @@ -149,7 +160,8 @@ export class SoloBlockBuilder implements BlockBuilder { protected async runCircuits( globalVariables: GlobalVariables, txs: ProcessedTx[], - newL1ToL2Messages: Fr[], + newModelL1ToL2Messages: Fr[], // TODO(#4492): Rename this when purging the old inbox + newL1ToL2Messages: Fr[], // TODO(#4492): Nuke this when purging the old inbox ): Promise<[RootRollupPublicInputs, Proof]> { // Check that the length of the array of txs is a power of two // See https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 @@ -157,71 +169,154 @@ export class SoloBlockBuilder implements BlockBuilder { throw new Error(`Length of txs for the block should be a power of two and at least two (got ${txs.length})`); } + // BASE PARITY CIRCUIT (run in parallel) + let baseParityInputs: BaseParityInputs[] = []; + let elapsedBaseParityOutputsPromise: Promise<[number, RootParityInput[]]>; + { + const newModelL1ToL2MessagesTuple = padArrayEnd( + newModelL1ToL2Messages, + Fr.ZERO, + NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, + ); + baseParityInputs = Array.from({ length: NUM_BASE_PARITY_PER_ROOT_PARITY }, (_, i) => + BaseParityInputs.fromSlice(newModelL1ToL2MessagesTuple, i), + ); + + const baseParityOutputs: Promise[] = []; + for (const inputs of baseParityInputs) { + baseParityOutputs.push(this.baseParityCircuit(inputs)); + } + elapsedBaseParityOutputsPromise = elapsed(() => Promise.all(baseParityOutputs)); + } + // padArrayEnd throws if the array is already full. Otherwise it pads till we reach the required size const newL1ToL2MessagesTuple = padArrayEnd(newL1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP); - // Perform all tree insertions and retrieve snapshots for all base rollups + // BASE ROLLUP CIRCUIT (run in parallel) + let elapsedBaseRollupOutputsPromise: Promise<[number, [BaseOrMergeRollupPublicInputs, Proof][]]>; const baseRollupInputs: BaseRollupInputs[] = []; - const treeSnapshots: Map[] = []; - for (const tx of txs) { - const input = await this.buildBaseRollupInput(tx, globalVariables); - baseRollupInputs.push(input); - const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map( - async (id: MerkleTreeId) => { - return { key: id, value: await this.getTreeSnapshot(id) }; - }, - ); - const snapshots: Map = new Map( - (await Promise.all(promises)).map(obj => [obj.key, obj.value]), - ); - treeSnapshots.push(snapshots); - } + { + // Perform all tree insertions and retrieve snapshots for all base rollups + const treeSnapshots: Map[] = []; + for (const tx of txs) { + const input = await this.buildBaseRollupInput(tx, globalVariables); + baseRollupInputs.push(input); + const promises = [MerkleTreeId.NOTE_HASH_TREE, MerkleTreeId.NULLIFIER_TREE, MerkleTreeId.PUBLIC_DATA_TREE].map( + async (id: MerkleTreeId) => { + return { key: id, value: await this.getTreeSnapshot(id) }; + }, + ); + const snapshots: Map = new Map( + (await Promise.all(promises)).map(obj => [obj.key, obj.value]), + ); + treeSnapshots.push(snapshots); + } - // Run the base rollup circuits for the txs in parallel - const baseRollupOutputs: Promise<[BaseOrMergeRollupPublicInputs, Proof]>[] = []; - for (let i = 0; i < txs.length; i++) { - baseRollupOutputs.push(this.baseRollupCircuit(txs[i], baseRollupInputs[i], treeSnapshots[i])); - } + // Run the base rollup circuits for the txs in parallel + const baseRollupOutputs: Promise<[BaseOrMergeRollupPublicInputs, Proof]>[] = []; + for (let i = 0; i < txs.length; i++) { + baseRollupOutputs.push(this.baseRollupCircuit(txs[i], baseRollupInputs[i], treeSnapshots[i])); + } - // Run merge rollups in layers until we have only two outputs - // All merge circuits for each layer are simulated in parallel - const [duration, mergeInputs] = await elapsed(() => Promise.all(baseRollupOutputs)); - for (let i = 0; i < mergeInputs.length; i++) { - this.debug(`Simulated base rollup circuit`, { - eventName: 'circuit-simulation', - circuitName: 'base-rollup', - duration: duration / mergeInputs.length, - inputSize: baseRollupInputs[i].toBuffer().length, - outputSize: mergeInputs[i][0].toBuffer().length, - } satisfies CircuitSimulationStats); + elapsedBaseRollupOutputsPromise = elapsed(() => Promise.all(baseRollupOutputs)); } - let mergeRollupInputs: [BaseOrMergeRollupPublicInputs, Proof][] = mergeInputs; - while (mergeRollupInputs.length > 2) { - const mergeInputStructs: MergeRollupInputs[] = []; - for (const pair of chunk(mergeRollupInputs, 2)) { - const [r1, r2] = pair; - mergeInputStructs.push(this.createMergeRollupInputs(r1, r2)); + + // ROOT PARITY CIRCUIT + let elapsedRootParityOutputPromise: Promise<[number, RootParityInput]>; + let rootParityInputs: RootParityInputs; + { + // First we await the base parity outputs + const [duration, baseParityOutputs] = await elapsedBaseParityOutputsPromise; + + // We emit stats for base parity circuits + for (let i = 0; i < baseParityOutputs.length; i++) { + this.debug(`Simulated base parity circuit`, { + eventName: 'circuit-simulation', + circuitName: 'base-parity', + duration: duration / baseParityOutputs.length, + inputSize: baseParityInputs[i].toBuffer().length, + outputSize: baseParityOutputs[i].toBuffer().length, + } satisfies CircuitSimulationStats); } - const [duration, mergeOutputs] = await elapsed(() => - Promise.all(mergeInputStructs.map(async input => await this.mergeRollupCircuit(input))), + rootParityInputs = new RootParityInputs( + baseParityOutputs as Tuple, ); + elapsedRootParityOutputPromise = elapsed(() => this.rootParityCircuit(rootParityInputs)); + } + + // MERGE ROLLUP CIRCUIT (each layer run in parallel) + let mergeOutputLeft: [BaseOrMergeRollupPublicInputs, Proof]; + let mergeOutputRight: [BaseOrMergeRollupPublicInputs, Proof]; + { + // Run merge rollups in layers until we have only two outputs + const [duration, mergeInputs] = await elapsedBaseRollupOutputsPromise; - for (let i = 0; i < mergeOutputs.length; i++) { - this.debug(`Simulated merge rollup circuit`, { + // We emit stats for base rollup circuits + for (let i = 0; i < mergeInputs.length; i++) { + this.debug(`Simulated base rollup circuit`, { eventName: 'circuit-simulation', - circuitName: 'merge-rollup', - duration: duration / mergeOutputs.length, - inputSize: mergeInputStructs[i].toBuffer().length, - outputSize: mergeOutputs[i][0].toBuffer().length, + circuitName: 'base-rollup', + duration: duration / mergeInputs.length, + inputSize: baseRollupInputs[i].toBuffer().length, + outputSize: mergeInputs[i][0].toBuffer().length, } satisfies CircuitSimulationStats); } - mergeRollupInputs = mergeOutputs; + + let mergeRollupInputs: [BaseOrMergeRollupPublicInputs, Proof][] = mergeInputs; + while (mergeRollupInputs.length > 2) { + const mergeInputStructs: MergeRollupInputs[] = []; + for (const pair of chunk(mergeRollupInputs, 2)) { + const [r1, r2] = pair; + mergeInputStructs.push(this.createMergeRollupInputs(r1, r2)); + } + + const [duration, mergeOutputs] = await elapsed(() => + Promise.all(mergeInputStructs.map(async input => await this.mergeRollupCircuit(input))), + ); + + // We emit stats for merge rollup circuits + for (let i = 0; i < mergeOutputs.length; i++) { + this.debug(`Simulated merge rollup circuit`, { + eventName: 'circuit-simulation', + circuitName: 'merge-rollup', + duration: duration / mergeOutputs.length, + inputSize: mergeInputStructs[i].toBuffer().length, + outputSize: mergeOutputs[i][0].toBuffer().length, + } satisfies CircuitSimulationStats); + } + mergeRollupInputs = mergeOutputs; + } + + // Run the root rollup with the last two merge rollups (or base, if no merge layers) + [mergeOutputLeft, mergeOutputRight] = mergeRollupInputs; } - // Run the root rollup with the last two merge rollups (or base, if no merge layers) - const [mergeOutputLeft, mergeOutputRight] = mergeRollupInputs; - return this.rootRollupCircuit(mergeOutputLeft, mergeOutputRight, newL1ToL2MessagesTuple); + // Finally, we emit stats for root parity circuit + const [duration, rootParityOutput] = await elapsedRootParityOutputPromise; + this.debug(`Simulated root parity circuit`, { + eventName: 'circuit-simulation', + circuitName: 'root-parity', + duration: duration, + inputSize: rootParityInputs.toBuffer().length, + outputSize: rootParityOutput.toBuffer().length, + } satisfies CircuitSimulationStats); + + return this.rootRollupCircuit(mergeOutputLeft, mergeOutputRight, rootParityOutput, newL1ToL2MessagesTuple); + } + + protected async baseParityCircuit(inputs: BaseParityInputs): Promise { + this.debug(`Running base parity circuit`); + const parityPublicInputs = await this.simulator.baseParityCircuit(inputs); + const proof = await this.prover.getBaseParityProof(inputs, parityPublicInputs); + return new RootParityInput(proof, parityPublicInputs); + } + + protected async rootParityCircuit(inputs: RootParityInputs): Promise { + this.debug(`Running root parity circuit`); + const parityPublicInputs = await this.simulator.rootParityCircuit(inputs); + const proof = await this.prover.getRootParityProof(inputs, parityPublicInputs); + return new RootParityInput(proof, parityPublicInputs); } protected async baseRollupCircuit( @@ -269,10 +364,11 @@ export class SoloBlockBuilder implements BlockBuilder { protected async rootRollupCircuit( left: [BaseOrMergeRollupPublicInputs, Proof], right: [BaseOrMergeRollupPublicInputs, Proof], + l1ToL2Roots: RootParityInput, newL1ToL2Messages: Tuple, ): Promise<[RootRollupPublicInputs, Proof]> { this.debug(`Running root rollup circuit`); - const rootInput = await this.getRootRollupInput(...left, ...right, newL1ToL2Messages); + const rootInput = await this.getRootRollupInput(...left, ...right, l1ToL2Roots, newL1ToL2Messages); // Update the local trees to include the new l1 to l2 messages await this.db.appendLeaves( @@ -365,6 +461,7 @@ export class SoloBlockBuilder implements BlockBuilder { rollupProofLeft: Proof, rollupOutputRight: BaseOrMergeRollupPublicInputs, rollupProofRight: Proof, + l1ToL2Roots: RootParityInput, newL1ToL2Messages: Tuple, ) { const vk = this.getVerificationKey(rollupOutputLeft.rollupType); @@ -406,6 +503,7 @@ export class SoloBlockBuilder implements BlockBuilder { return RootRollupInputs.from({ previousRollupData, + l1ToL2Roots, newL1ToL2Messages, newL1ToL2MessageTreeRootSiblingPath, startL1ToL2MessageTreeSnapshot, diff --git a/yarn-project/sequencer-client/src/prover/empty.ts b/yarn-project/sequencer-client/src/prover/empty.ts index 6bf915b7213..7ca043c8f8f 100644 --- a/yarn-project/sequencer-client/src/prover/empty.ts +++ b/yarn-project/sequencer-client/src/prover/empty.ts @@ -2,11 +2,14 @@ import { AggregationObject, BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, MergeRollupInputs, + ParityPublicInputs, Proof, PublicCircuitPublicInputs, PublicKernelCircuitPublicInputs, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, } from '@aztec/circuits.js'; @@ -22,6 +25,26 @@ const EMPTY_PROOF_SIZE = 42; * Prover implementation that returns empty proofs and overrides aggregation objects. */ export class EmptyRollupProver implements RollupProver { + /** + * Creates an empty proof for the given input. + * @param inputs - Inputs to the circuit. + * @param publicInputs - Public inputs of the circuit obtained via simulation, modified by this call. + */ + async getBaseParityProof(inputs: BaseParityInputs, publicInputs: ParityPublicInputs): Promise { + publicInputs.aggregationObject = AggregationObject.makeFake(); + return new Proof(Buffer.alloc(EMPTY_PROOF_SIZE, 0)); + } + + /** + * Creates an empty proof for the given input. + * @param inputs - Inputs to the circuit. + * @param publicInputs - Public inputs of the circuit obtained via simulation, modified by this call. + */ + async getRootParityProof(inputs: RootParityInputs, publicInputs: ParityPublicInputs): Promise { + publicInputs.aggregationObject = AggregationObject.makeFake(); + return new Proof(Buffer.alloc(EMPTY_PROOF_SIZE, 0)); + } + /** * Creates an empty proof for the given input. * @param _input - Input to the circuit. diff --git a/yarn-project/sequencer-client/src/prover/index.ts b/yarn-project/sequencer-client/src/prover/index.ts index 00935fbecee..333d872cb96 100644 --- a/yarn-project/sequencer-client/src/prover/index.ts +++ b/yarn-project/sequencer-client/src/prover/index.ts @@ -1,18 +1,35 @@ import { BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, MergeRollupInputs, + ParityPublicInputs, Proof, PublicCircuitPublicInputs, PublicKernelCircuitPublicInputs, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, } from '@aztec/circuits.js'; /** - * Generates proofs for the base, merge, and root rollup circuits. + * Generates proofs for parity and rollup circuits. */ export interface RollupProver { + /** + * Creates a proof for the given input. + * @param input - Input to the circuit. + * @param publicInputs - Public inputs of the circuit obtained via simulation, modified by this call. + */ + getBaseParityProof(inputs: BaseParityInputs, publicInputs: ParityPublicInputs): Promise; + + /** + * Creates a proof for the given input. + * @param input - Input to the circuit. + * @param publicInputs - Public inputs of the circuit obtained via simulation, modified by this call. + */ + getRootParityProof(inputs: RootParityInputs, publicInputs: ParityPublicInputs): Promise; + /** * Creates a proof for the given input. * @param input - Input to the circuit. diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 831ddb4c2fb..589d745d554 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -73,6 +73,7 @@ describe('sequencer', () => { }); l1ToL2MessageSource = mock({ + getNewL1ToL2Messages: () => Promise.resolve(Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(Fr.ZERO)), getPendingL1ToL2EntryKeys: () => Promise.resolve(Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(Fr.ZERO)), getBlockNumber: () => Promise.resolve(lastBlockNumber), }); @@ -111,6 +112,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient), expectedTxHashes.map(hash => expect.objectContaining({ hash })), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), + Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); }); @@ -148,6 +150,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient), expectedTxHashes.map(hash => expect.objectContaining({ hash })), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), + Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(p2p.deleteTxs).toHaveBeenCalledWith([doubleSpendTx.getTxHash()]); @@ -181,6 +184,7 @@ describe('sequencer', () => { new GlobalVariables(chainId, version, new Fr(lastBlockNumber + 1), Fr.ZERO, coinbase, feeRecipient), expectedTxHashes.map(hash => expect.objectContaining({ hash })), Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), + Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(new Fr(0n)), ); expect(publisher.processL2Block).toHaveBeenCalledWith(block); expect(p2p.deleteTxs).toHaveBeenCalledWith([invalidChainTx.getTxHash()]); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 39f9b12e058..f22ec684ff7 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -202,6 +202,8 @@ export class Sequencer { await assertBlockHeight(); + const newModelL1ToL2Messages = await this.l1ToL2MessageSource.getNewL1ToL2Messages(BigInt(newBlockNumber)); + // Get l1 to l2 messages from the contract this.log('Requesting L1 to L2 messages from contract'); const l1ToL2Messages = await this.getPendingL1ToL2EntryKeys(); @@ -214,7 +216,7 @@ export class Sequencer { const emptyTx = processor.makeEmptyProcessedTx(); const [rollupCircuitsDuration, block] = await elapsed(() => - this.buildBlock(processedValidTxs, l1ToL2Messages, emptyTx, newGlobalVariables), + this.buildBlock(processedValidTxs, newModelL1ToL2Messages, l1ToL2Messages, emptyTx, newGlobalVariables), ); this.log(`Assembled block ${block.number}`, { @@ -312,6 +314,7 @@ export class Sequencer { /** * Pads the set of txs to a power of two and assembles a block by calling the block builder. * @param txs - Processed txs to include in the next block. + * @param newModelL1ToL2Messages - L1 to L2 messages emitted by the new inbox. * @param newL1ToL2Messages - L1 to L2 messages to be part of the block. * @param emptyTx - Empty tx to repeat at the end of the block to pad to a power of two. * @param globalVariables - Global variables to use in the block. @@ -319,7 +322,8 @@ export class Sequencer { */ protected async buildBlock( txs: ProcessedTx[], - newL1ToL2Messages: Fr[], + newModelL1ToL2Messages: Fr[], // TODO(#4492): Rename this when purging the old inbox + newL1ToL2Messages: Fr[], // TODO(#4492): Nuke this when purging the old inbox emptyTx: ProcessedTx, globalVariables: GlobalVariables, ) { @@ -330,7 +334,12 @@ export class Sequencer { const allTxs = [...txs, ...times(emptyTxCount, () => emptyTx)]; this.log(`Building block ${globalVariables.blockNumber}`); - const [block] = await this.blockBuilder.buildL2Block(globalVariables, allTxs, newL1ToL2Messages); + const [block] = await this.blockBuilder.buildL2Block( + globalVariables, + allTxs, + newModelL1ToL2Messages, + newL1ToL2Messages, + ); return block; } diff --git a/yarn-project/sequencer-client/src/simulator/index.ts b/yarn-project/sequencer-client/src/simulator/index.ts index b23aa903b14..9f25ce30388 100644 --- a/yarn-project/sequencer-client/src/simulator/index.ts +++ b/yarn-project/sequencer-client/src/simulator/index.ts @@ -1,10 +1,13 @@ import { BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, MergeRollupInputs, + ParityPublicInputs, PublicKernelCircuitPrivateInputs, PublicKernelCircuitPublicInputs, PublicKernelTailCircuitPrivateInputs, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, } from '@aztec/circuits.js'; @@ -13,6 +16,18 @@ import { * Circuit simulator for the rollup circuits. */ export interface RollupSimulator { + /** + * Simulates the base parity circuit from its inputs. + * @param inputs - Inputs to the circuit. + * @returns The public inputs of the parity circuit. + */ + baseParityCircuit(inputs: BaseParityInputs): Promise; + /** + * Simulates the root parity circuit from its inputs. + * @param inputs - Inputs to the circuit. + * @returns The public inputs of the parity circuit. + */ + rootParityCircuit(inputs: RootParityInputs): Promise; /** * Simulates the base rollup circuit from its inputs. * @param input - Inputs to the circuit. diff --git a/yarn-project/sequencer-client/src/simulator/rollup.ts b/yarn-project/sequencer-client/src/simulator/rollup.ts index 02dbc9a5535..e87f6e38816 100644 --- a/yarn-project/sequencer-client/src/simulator/rollup.ts +++ b/yarn-project/sequencer-client/src/simulator/rollup.ts @@ -1,21 +1,30 @@ import { CircuitSimulationStats } from '@aztec/circuit-types/stats'; import { BaseOrMergeRollupPublicInputs, + BaseParityInputs, BaseRollupInputs, MergeRollupInputs, + ParityPublicInputs, + RootParityInputs, RootRollupInputs, RootRollupPublicInputs, } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { elapsed } from '@aztec/foundation/timer'; import { + BaseParityArtifact, BaseRollupArtifact, MergeRollupArtifact, + RootParityArtifact, RootRollupArtifact, + convertBaseParityInputsToWitnessMap, + convertBaseParityOutputsFromWitnessMap, convertBaseRollupInputsToWitnessMap, convertBaseRollupOutputsFromWitnessMap, convertMergeRollupInputsToWitnessMap, convertMergeRollupOutputsFromWitnessMap, + convertRootParityInputsToWitnessMap, + convertRootParityOutputsFromWitnessMap, convertRootRollupInputsToWitnessMap, convertRootRollupOutputsFromWitnessMap, } from '@aztec/noir-protocol-circuits-types'; @@ -34,6 +43,36 @@ export class RealRollupCircuitSimulator implements RollupSimulator { constructor(private simulationProvider: SimulationProvider) {} + /** + * Simulates the base parity circuit from its inputs. + * @param inputs - Inputs to the circuit. + * @returns The public inputs of the parity circuit. + */ + public async baseParityCircuit(inputs: BaseParityInputs): Promise { + const witnessMap = convertBaseParityInputsToWitnessMap(inputs); + + const witness = await this.simulationProvider.simulateCircuit(witnessMap, BaseParityArtifact); + + const result = convertBaseParityOutputsFromWitnessMap(witness); + + return Promise.resolve(result); + } + + /** + * Simulates the root parity circuit from its inputs. + * @param inputs - Inputs to the circuit. + * @returns The public inputs of the parity circuit. + */ + public async rootParityCircuit(inputs: RootParityInputs): Promise { + const witnessMap = convertRootParityInputsToWitnessMap(inputs); + + const witness = await this.simulationProvider.simulateCircuit(witnessMap, RootParityArtifact); + + const result = convertRootParityOutputsFromWitnessMap(witness); + + return Promise.resolve(result); + } + /** * Simulates the base rollup circuit from its inputs. * @param input - Inputs to the circuit.