diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index 119d630749b..d03df4559da 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -10,6 +10,7 @@ import {IInbox} from "@aztec/core/interfaces/messagebridge/IInbox.sol"; import {IOutbox} from "@aztec/core/interfaces/messagebridge/IOutbox.sol"; import {Leonidas} from "@aztec/core/Leonidas.sol"; import {Constants} from "@aztec/core/libraries/ConstantsGen.sol"; +import {Hash} from "@aztec/core/libraries/crypto/Hash.sol"; import {MerkleLib} from "@aztec/core/libraries/crypto/MerkleLib.sol"; import {SignatureLib} from "@aztec/core/libraries/crypto/SignatureLib.sol"; import {DataStructures} from "@aztec/core/libraries/DataStructures.sol"; @@ -52,14 +53,6 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { Slot slotNumber; } - // Blob public inputs are stored when we publish blocks to link DA to a L1 blob. They are read and used - // when verifying an epoch proof to link DA to our L2 blocks. - struct BlobPublicInputs { - bytes32 z; - bytes32 y; - bytes32[2] c; - } - struct Config { uint256 aztecSlotDuration; uint256 aztecEpochDuration; @@ -94,7 +87,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { mapping(uint256 blockNumber => BlockLog log) public blocks; // The below public inputs are filled when proposing a block, then used to verify an epoch proof. // TODO(#8955): When implementing batched kzg proofs, store one instance per epoch rather than block - mapping(uint256 blockNumber => BlobPublicInputs) public blobPublicInputs; + mapping(uint256 blockNumber => bytes32) public blobPublicInputsHashes; bytes32 public vkTreeRoot; bytes32 public protocolContractTreeRoot; @@ -252,14 +245,14 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { * @param _epochSize - The size of the epoch (to be promoted to a constant) * @param _args - Array of public inputs to the proof (previousArchive, endArchive, previousBlockHash, endBlockHash, endTimestamp, outHash, proverId) * @param _fees - Array of recipient-value pairs with fees to be distributed for the epoch - * @param _aggregationObject - The aggregation object for the proof + * @param _blobPublicInputsAndAggregationObject - The aggregation object and blob PIs for the proof * @param _proof - The proof to verify */ function submitEpochRootProof( uint256 _epochSize, bytes32[7] calldata _args, bytes32[] calldata _fees, - bytes calldata _aggregationObject, + bytes calldata _blobPublicInputsAndAggregationObject, // having separate inputs here caused stack too deep bytes calldata _proof ) external override(IRollup) { if (canPrune()) { @@ -275,7 +268,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { Epoch epochToProve = getEpochForBlock(endBlockNumber); bytes32[] memory publicInputs = - getEpochProofPublicInputs(_epochSize, _args, _fees, _aggregationObject); + getEpochProofPublicInputs(_epochSize, _args, _fees, _blobPublicInputsAndAggregationObject); require(epochProofVerifier.verify(_proof, publicInputs), Errors.Rollup__InvalidProof()); @@ -333,7 +326,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { for (uint256 i = 0; i < _epochSize; i++) { // free up gas (hopefully) - delete blobPublicInputs[previousBlockNumber + i + 1]; + delete blobPublicInputsHashes[previousBlockNumber + i + 1]; } if (proofClaim.epochToProve == epochToProve) { PROOF_COMMITMENT_ESCROW.unstakeBond(proofClaim.bondProvider, proofClaim.bondAmount); @@ -509,22 +502,24 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { } // Since an invalid blob hash here would fail the consensus checks of // the header, the `blobInput` is implicitly accepted by consensus as well. - bytes32 blobHash = _validateBlob(_blobInput); + (bytes32 blobsHash, bytes32 blobPublicInputsHash) = _validateBlobs(_blobInput); // Decode and validate header HeaderLib.Header memory header = HeaderLib.decode(_header); - uint8 domainSeperator = uint8(SignatureLib.SignatureDomainSeperator.blockAttestation); - bytes32 digest = keccak256(abi.encode(domainSeperator, _archive, _txHashes)); - setupEpoch(); - _validateHeader({ - _header: header, - _signatures: _signatures, - _digest: digest, - _currentTime: Timestamp.wrap(block.timestamp), - _blobHash: blobHash, - _flags: DataStructures.ExecutionFlags({ignoreDA: false, ignoreSignatures: false}) - }); + { + uint8 domainSeperator = uint8(SignatureLib.SignatureDomainSeperator.blockAttestation); + bytes32 digest = keccak256(abi.encode(domainSeperator, _archive, _txHashes)); + setupEpoch(); + _validateHeader({ + _header: header, + _signatures: _signatures, + _digest: digest, + _currentTime: Timestamp.wrap(block.timestamp), + _blobHash: blobsHash, + _flags: DataStructures.ExecutionFlags({ignoreDA: false, ignoreSignatures: false}) + }); + } uint256 blockNumber = ++tips.pendingBlockNumber; @@ -534,20 +529,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { slotNumber: Slot.wrap(header.globalVariables.slotNumber) }); - // Blob public inputs structure: - // * input[32:64] - z - // * input[64:96] - y - // * input[96:144] - commitment C - blobPublicInputs[blockNumber] = BlobPublicInputs({ - z: bytes32(_blobInput[32:64]), - y: bytes32(_blobInput[64:96]), - // To fit into 2 fields, the commitment is split into 31 and 17 byte numbers - // TODO: The below left pads, possibly inefficiently - c: [ - bytes32(uint256(uint248(bytes31(_blobInput[96:127])))), - bytes32(uint256(uint136(bytes17(_blobInput[127:144])))) - ] - }); + blobPublicInputsHashes[blockNumber] = blobPublicInputsHash; // @note The block number here will always be >=1 as the genesis block is at 0 bytes32 inHash = INBOX.consume(blockNumber); @@ -604,13 +586,13 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { * @param _epochSize - The size of the epoch (to be promoted to a constant) * @param _args - Array of public inputs to the proof (previousArchive, endArchive, previousBlockHash, endBlockHash, endTimestamp, outHash, proverId) * @param _fees - Array of recipient-value pairs with fees to be distributed for the epoch - * @param _aggregationObject - The aggregation object for the proof + * @param _blobPublicInputsAndAggregationObject - The aggregation object and blob PIs for the proof */ function getEpochProofPublicInputs( uint256 _epochSize, bytes32[7] calldata _args, bytes32[] calldata _fees, - bytes calldata _aggregationObject + bytes calldata _blobPublicInputsAndAggregationObject // having separate inputs here caused stack too deep ) public view override(IRollup) returns (bytes32[] memory) { uint256 previousBlockNumber = tips.provenBlockNumber; uint256 endBlockNumber = previousBlockNumber + _epochSize; @@ -671,7 +653,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { // vk_tree_root: Field, // protocol_contract_tree_root: Field, // prover_id: Field, - // blob_public_inputs: [BlobPublicInputs; Constants.AZTEC_MAX_EPOCH_DURATION], // <--This will be reduced to 1 if/when we implement multi-opening for blob verification + // blob_public_inputs: [BlockBlobPublicInputs; Constants.AZTEC_MAX_EPOCH_DURATION], // <--This will be reduced to 1 if/when we implement multi-opening for blob verification // } // previous_archive.root: the previous archive tree root @@ -708,35 +690,79 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { for (uint256 i = 0; i < feesLength; i++) { publicInputs[9 + i] = _fees[i]; } - uint256 feesEnd = 9 + feesLength; + uint256 offset = 9 + feesLength; // vk_tree_root - publicInputs[feesEnd] = vkTreeRoot; + publicInputs[offset] = vkTreeRoot; + offset += 1; // protocol_contract_tree_root - publicInputs[feesEnd + 1] = protocolContractTreeRoot; + publicInputs[offset] = protocolContractTreeRoot; + offset += 1; // prover_id: id of current epoch's prover - publicInputs[feesEnd + 2] = _args[6]; + publicInputs[offset] = _args[6]; + offset += 1; // blob_public_inputs + uint256 blobOffset = 0; for (uint256 i = 0; i < _epochSize; i++) { - uint256 j = feesEnd + 3 + i * 6; - publicInputs[j] = blobPublicInputs[previousBlockNumber + i + 1].z; - (publicInputs[j + 1], publicInputs[j + 2], publicInputs[j + 3]) = - _bytes32ToBigNum(blobPublicInputs[previousBlockNumber + i + 1].y); - publicInputs[j + 4] = blobPublicInputs[previousBlockNumber + i + 1].c[0]; - publicInputs[j + 5] = blobPublicInputs[previousBlockNumber + i + 1].c[1]; + uint8 blobsInBlock = uint8(_blobPublicInputsAndAggregationObject[blobOffset++]); + // asserting here to avoid looping twice in one fn + { + // Blob public inputs are 112 bytes long - see _validateBlobs() for explanation + bytes32 calcBlobPublicInputsHash = sha256( + abi.encodePacked( + _blobPublicInputsAndAggregationObject[blobOffset:blobOffset + 112 * blobsInBlock] + ) + ); + require( + calcBlobPublicInputsHash == blobPublicInputsHashes[previousBlockNumber + i + 1], + Errors.Rollup__InvalidBlobPublicInputsHash( + blobPublicInputsHashes[previousBlockNumber + i + 1], calcBlobPublicInputsHash + ) + ); + } + for (uint256 j = 0; j < Constants.BLOBS_PER_BLOCK; j++) { + if (j < blobsInBlock) { + // z + publicInputs[offset++] = + bytes32(_blobPublicInputsAndAggregationObject[blobOffset:blobOffset += 32]); + // y + (publicInputs[offset++], publicInputs[offset++], publicInputs[offset++]) = + _bytes32ToBigNum( + bytes32(_blobPublicInputsAndAggregationObject[blobOffset:blobOffset += 32]) + ); + // To fit into 2 fields, the commitment is split into 31 and 17 byte numbers + // TODO: The below left pads, possibly inefficiently + // c[0] + publicInputs[offset++] = bytes32( + uint256( + uint248(bytes31(_blobPublicInputsAndAggregationObject[blobOffset:blobOffset += 31])) + ) + ); + // c[1] + publicInputs[offset++] = bytes32( + uint256( + uint136(bytes17(_blobPublicInputsAndAggregationObject[blobOffset:blobOffset += 17])) + ) + ); + } else { + offset += Constants.BLOB_PUBLIC_INPUTS; + } + } } // the block proof is recursive, which means it comes with an aggregation object // this snippet copies it into the public inputs needed for verification // it also guards against empty _aggregationObject used with mocked proofs - uint256 aggregationLength = _aggregationObject.length / 32; + uint256 aggregationLength = + bytes(_blobPublicInputsAndAggregationObject[blobOffset:]).length / 32; for (uint256 i = 0; i < Constants.AGGREGATION_OBJECT_LENGTH && i < aggregationLength; i++) { bytes32 part; assembly { - part := calldataload(add(_aggregationObject.offset, mul(i, 32))) + part := + calldataload(add(_blobPublicInputsAndAggregationObject.offset, add(mul(i, 32), blobOffset))) } publicInputs[i + Constants.ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH] = part; } @@ -1033,11 +1059,8 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { require(timestamp <= _currentTime, Errors.Rollup__TimestampInFuture(_currentTime, timestamp)); // Check if the data is available - // To fit into a field, we remove the first byte (= VERSIONED_HASH_VERSION_KZG) - bytes32 truncatedBlobHash = - bytes32(bytes.concat(new bytes(1), bytes31(uint248(uint256(_blobHash))))); require( - _flags.ignoreDA || _header.contentCommitment.blobHash == truncatedBlobHash, + _flags.ignoreDA || _header.contentCommitment.blobHash == _blobHash, Errors.Rollup__UnavailableTxs(_header.contentCommitment.blobHash) ); @@ -1049,7 +1072,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { } /** - * @notice Validate an L2 block's blob. TODO: edit for multiple blobs per block + * @notice Validate a blob. * Input bytes: * input[:32] - versioned_hash * input[32:64] - z @@ -1057,15 +1080,20 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { * input[96:144] - commitment C * input[144:192] - proof (a commitment to the quotient polynomial q(X)) * - This can be relaxed to happen at the time of `submitProof` instead - * + * @notice Apparently there is no guarantee that the blobs will be processed in the order sent + * so the use of blobhash(_blobNumber) may fail in production * @param _blobInput - The above bytes to verify a blob */ - function _validateBlob(bytes calldata _blobInput) internal view returns (bytes32 blobHash) { + function _validateBlob(bytes calldata _blobInput, uint256 _blobNumber) + internal + view + returns (bytes32 blobHash) + { if (!checkBlob) { return bytes32(_blobInput[0:32]); } assembly { - blobHash := blobhash(0) + blobHash := blobhash(_blobNumber) } require(blobHash == bytes32(_blobInput[0:32]), Errors.Rollup__InvalidBlobHash(blobHash)); @@ -1074,6 +1102,43 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup { require(success, Errors.Rollup__InvalidBlobProof(blobHash)); } + /** + * @notice Validate an L2 block's blobs and return the hashed blobHashes and public inputs. + * Input bytes: + * input[:1] - num blobs in block + * input[1:] - 192 * num blobs of the above _blobInput + * @param _blobsInput - The above bytes to verify a blob + */ + function _validateBlobs(bytes calldata _blobsInput) + internal + view + returns (bytes32 blobsHash, bytes32 blobPublicInputsHash) + { + // We cannot input the incorrect number of blobs below, as the blobsHash + // and epoch proof verification will fail. + uint8 numBlobs = uint8(_blobsInput[0]); + bytes32[] memory blobHashes = new bytes32[](numBlobs); + bytes memory blobPublicInputs; + for (uint256 i = 0; i < numBlobs; i++) { + // Add 1 for the numBlobs prefix + uint256 blobInputStart = i * 192 + 1; + // Since an invalid blob hash here would fail the consensus checks of + // the header, the `blobInput` is implicitly accepted by consensus as well. + blobHashes[i] = _validateBlob(_blobsInput[blobInputStart:blobInputStart + 192], i); + // We want to extract the 112 bytes we use for public inputs: + // * input[32:64] - z + // * input[64:96] - y + // * input[96:144] - commitment C + // Out of 192 bytes per blob. + blobPublicInputs = + abi.encodePacked(blobPublicInputs, _blobsInput[blobInputStart + 32:blobInputStart + 144]); + } + // Return the hash of all z, y, and Cs, so we can use them in proof verification later + blobPublicInputsHash = sha256(blobPublicInputs); + // Hash the EVM blob hashes for the block header + blobsHash = Hash.sha256ToField(abi.encodePacked(blobHashes)); + } + /** * @notice Converts a BLS12 field element from bytes32 to a nr BigNum type * The nr bignum type for BLS12 fields is encoded as 3 nr fields - see blob_public_inputs.ts: diff --git a/l1-contracts/src/core/interfaces/IRollup.sol b/l1-contracts/src/core/interfaces/IRollup.sol index 8aa7f42d227..4e0ec9766e5 100644 --- a/l1-contracts/src/core/interfaces/IRollup.sol +++ b/l1-contracts/src/core/interfaces/IRollup.sol @@ -59,7 +59,7 @@ interface IRollup { uint256 _epochSize, bytes32[7] calldata _args, bytes32[] calldata _fees, - bytes calldata _aggregationObject, + bytes calldata _blobPublicInputsAndAggregationObject, bytes calldata _proof ) external; @@ -117,7 +117,7 @@ interface IRollup { uint256 _epochSize, bytes32[7] calldata _args, bytes32[] calldata _fees, - bytes calldata _aggregationObject + bytes calldata _blobPublicInputsAndAggregationObject ) external view returns (bytes32[] memory); function computeTxsEffectsHash(bytes calldata _body) external pure returns (bytes32); } diff --git a/l1-contracts/src/core/libraries/ConstantsGen.sol b/l1-contracts/src/core/libraries/ConstantsGen.sol index 8ea072f1896..e8c9d5048d9 100644 --- a/l1-contracts/src/core/libraries/ConstantsGen.sol +++ b/l1-contracts/src/core/libraries/ConstantsGen.sol @@ -95,6 +95,7 @@ library Constants { uint256 internal constant INITIALIZATION_SLOT_SEPARATOR = 1000000000; uint256 internal constant INITIAL_L2_BLOCK_NUM = 1; uint256 internal constant FIELDS_PER_BLOB = 4096; + uint256 internal constant BLOBS_PER_BLOCK = 3; uint256 internal constant PRIVATE_LOG_SIZE_IN_BYTES = 576; uint256 internal constant AZTEC_MAX_EPOCH_DURATION = 32; uint256 internal constant GENESIS_ARCHIVE_ROOT = @@ -236,8 +237,8 @@ library Constants { uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 605; uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 13; uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 51; - uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 282; - uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 268; + uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 666; + uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 652; uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674; uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/l1-contracts/src/core/libraries/Errors.sol b/l1-contracts/src/core/libraries/Errors.sol index d96dc0f37da..a0408db7516 100644 --- a/l1-contracts/src/core/libraries/Errors.sol +++ b/l1-contracts/src/core/libraries/Errors.sol @@ -62,6 +62,7 @@ library Errors { error Rollup__InvalidVersion(uint256 expected, uint256 actual); // 0x9ef30794 error Rollup__InvalidBlobHash(bytes32 blobHash); // 0xc4a168c6 error Rollup__InvalidBlobProof(bytes32 blobHash); // 0x5ca17bef + error Rollup__InvalidBlobPublicInputsHash(bytes32 expected, bytes32 actual); // 0xfe6b4994 error Rollup__NoEpochToProve(); // 0xcbaa3951 error Rollup__NonSequentialProving(); // 0x1e5be132 error Rollup__NotClaimingCorrectEpoch(Epoch expected, Epoch actual); // 0xf0e0744d diff --git a/l1-contracts/test/Rollup.t.sol b/l1-contracts/test/Rollup.t.sol index 161a5906cbc..8701562c260 100644 --- a/l1-contracts/test/Rollup.t.sol +++ b/l1-contracts/test/Rollup.t.sol @@ -133,6 +133,35 @@ contract RollupTest is DecoderBase, TimeFns { vm.store(address(rollup), bytes32(uint256(20)), 0); } + function getBlobPublicInputs(bytes calldata _blobsInput) + public + pure + returns (bytes memory blobPublicInputs) + { + uint8 numBlobs = uint8(_blobsInput[0]); + blobPublicInputs = abi.encodePacked(numBlobs, blobPublicInputs); + for (uint256 i = 0; i < numBlobs; i++) { + // Add 1 for the numBlobs prefix + uint256 blobInputStart = i * 192 + 1; + // We want to extract the bytes we use for public inputs: + // * input[32:64] - z + // * input[64:96] - y + // * input[96:144] - commitment C + // Out of 192 bytes per blob. + blobPublicInputs = + abi.encodePacked(blobPublicInputs, _blobsInput[blobInputStart + 32:blobInputStart + 144]); + } + } + + function getBlobPublicInputsHash(bytes calldata _blobPublicInputs) + public + pure + returns (bytes32 publicInputsHash) + { + uint8 numBlobs = uint8(_blobPublicInputs[0]); + publicInputsHash = sha256(abi.encodePacked(_blobPublicInputs[1:1 + numBlobs * 112])); + } + function testClaimInTheFuture(uint256 _futureSlot) public setUpFor("mixed_block_1") { uint256 futureSlot = bound(_futureSlot, 1, 1e20); _testBlock("mixed_block_1", false, 1); @@ -255,11 +284,8 @@ contract RollupTest is DecoderBase, TimeFns { function testProofReleasesBond() public setUpFor("mixed_block_1") { DecoderBase.Data memory data = load("mixed_block_1").block; bytes memory header = data.header; - bytes32 archive = data.archive; - bytes32 blockHash = data.blockHash; bytes32 proverId = bytes32(uint256(42)); bytes memory body = data.body; - bytes32[] memory txHashes = new bytes32[](0); // We jump to the time of the block. (unless it is in the past) vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); @@ -267,13 +293,7 @@ contract RollupTest is DecoderBase, TimeFns { skipBlobCheck(); rollup.propose( - header, - archive, - blockHash, - txHashes, - signatures, - body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) + header, data.archive, data.blockHash, new bytes32[](0), signatures, body, data.blobInputs ); quote.epochToProve = Epoch.wrap(1); @@ -286,7 +306,16 @@ contract RollupTest is DecoderBase, TimeFns { proofCommitmentEscrow.deposits(quote.prover), quote.bondAmount * 9, "Invalid escrow balance" ); - _submitEpochProof(rollup, 1, preArchive, archive, preBlockHash, blockHash, proverId); + _submitEpochProof( + rollup, + 1, + preArchive, + data.archive, + preBlockHash, + data.blockHash, + proverId, + this.getBlobPublicInputs(data.blobInputs) + ); assertEq( proofCommitmentEscrow.deposits(quote.prover), quote.bondAmount * 10, "Invalid escrow balance" @@ -431,11 +460,7 @@ contract RollupTest is DecoderBase, TimeFns { function testRevertProveTwice() public setUpFor("mixed_block_1") { DecoderBase.Data memory data = load("mixed_block_1").block; bytes memory header = data.header; - bytes32 archive = data.archive; - bytes32 blockHash = data.blockHash; - bytes32 proverId = bytes32(uint256(42)); bytes memory body = data.body; - bytes32[] memory txHashes = new bytes32[](0); // We jump to the time of the block. (unless it is in the past) vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); @@ -443,20 +468,32 @@ contract RollupTest is DecoderBase, TimeFns { skipBlobCheck(); rollup.propose( - header, - archive, - blockHash, - txHashes, - signatures, - body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) + header, data.archive, data.blockHash, new bytes32[](0), signatures, body, data.blobInputs ); (bytes32 preArchive, bytes32 preBlockHash,) = rollup.blocks(0); - _submitEpochProof(rollup, 1, preArchive, archive, preBlockHash, blockHash, proverId); + _submitEpochProof( + rollup, + 1, + preArchive, + data.archive, + preBlockHash, + data.blockHash, + bytes32(uint256(42)), + this.getBlobPublicInputs(data.blobInputs) + ); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidBlockNumber.selector, 1, 2)); - _submitEpochProof(rollup, 1, preArchive, archive, preBlockHash, blockHash, proverId); + _submitEpochProof( + rollup, + 1, + preArchive, + data.archive, + preBlockHash, + data.blockHash, + bytes32(uint256(42)), + new bytes(112) + ); } function testTimestamp() public setUpFor("mixed_block_1") { @@ -484,28 +521,31 @@ contract RollupTest is DecoderBase, TimeFns { vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidBlobHash.selector, blobHashes[0])); rollup.propose( - header, data.archive, data.blockHash, txHashes, signatures, data.body, data.blobPublicInputs + header, data.archive, data.blockHash, txHashes, signatures, data.body, data.blobInputs ); } function testInvalidBlobProof() public setUpFor("mixed_block_1") { DecoderBase.Data memory data = load("mixed_block_1").block; bytes memory header = data.header; + bytes memory blobInput = data.blobInputs; bytes32[] memory txHashes = new bytes32[](0); // We set the blobHash to the correct value bytes32[] memory blobHashes = new bytes32[](1); - blobHashes[0] = bytes32(data.blobPublicInputs); + // The below is the blob hash == bytes [1:33] of _blobInput + bytes32 blobHash; + assembly { + blobHash := mload(add(blobInput, 0x21)) + } + blobHashes[0] = blobHash; vm.blobhashes(blobHashes); // We mess with the blob input bytes - bytes memory badBlobInput = data.blobPublicInputs; - badBlobInput[100] = 0x01; + blobInput[100] = 0x01; vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidBlobProof.selector, blobHashes[0])); - rollup.propose( - header, data.archive, data.blockHash, txHashes, signatures, data.body, badBlobInput - ); + rollup.propose(header, data.archive, data.blockHash, txHashes, signatures, data.body, blobInput); } function testRevertPrune() public setUpFor("mixed_block_1") { @@ -621,13 +661,7 @@ contract RollupTest is DecoderBase, TimeFns { vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__NonZeroDaFee.selector)); rollup.propose( - header, - data.archive, - data.blockHash, - txHashes, - signatures, - data.body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) + header, data.archive, data.blockHash, txHashes, signatures, data.body, data.blobInputs ); } @@ -649,13 +683,7 @@ contract RollupTest is DecoderBase, TimeFns { vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__NonZeroL2Fee.selector)); rollup.propose( - header, - data.archive, - data.blockHash, - txHashes, - signatures, - data.body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) + header, data.archive, data.blockHash, txHashes, signatures, data.body, data.blobInputs ); } @@ -663,9 +691,8 @@ contract RollupTest is DecoderBase, TimeFns { uint256 feeAmount = 2e18; DecoderBase.Data memory data = load("mixed_block_1").block; - bytes32[] memory txHashes = new bytes32[](0); uint256 portalBalance = testERC20.balanceOf(address(feeJuicePortal)); - address coinbase = data.decodedHeader.globalVariables.coinbase; + // address coinbase = data.decodedHeader.globalVariables.coinbase; // Progress time as necessary vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); @@ -681,7 +708,7 @@ contract RollupTest is DecoderBase, TimeFns { // We jump to the time of the block. (unless it is in the past) vm.warp(max(block.timestamp, data.decodedHeader.globalVariables.timestamp)); - uint256 coinbaseBalance = testERC20.balanceOf(coinbase); + uint256 coinbaseBalance = testERC20.balanceOf(data.decodedHeader.globalVariables.coinbase); assertEq(coinbaseBalance, 0, "invalid initial coinbase balance"); skipBlobCheck(); @@ -691,12 +718,16 @@ contract RollupTest is DecoderBase, TimeFns { header, data.archive, data.blockHash, - txHashes, + new bytes32[](0), signatures, data.body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) + data.blobInputs + ); + assertEq( + testERC20.balanceOf(data.decodedHeader.globalVariables.coinbase), + 0, + "invalid coinbase balance" ); - assertEq(testERC20.balanceOf(coinbase), 0, "invalid coinbase balance"); } (bytes32 preArchive, bytes32 preBlockHash,) = rollup.blocks(0); @@ -709,6 +740,7 @@ contract RollupTest is DecoderBase, TimeFns { rollup.claimEpochProofRight(signedQuote); { + bytes memory blobPublicInputs = this.getBlobPublicInputs(data.blobInputs); vm.expectRevert( abi.encodeWithSelector( IERC20Errors.ERC20InsufficientBalance.selector, @@ -725,11 +757,16 @@ contract RollupTest is DecoderBase, TimeFns { preBlockHash, data.blockHash, bytes32(uint256(42)), - coinbase, + blobPublicInputs, + data.decodedHeader.globalVariables.coinbase, feeAmount ); } - assertEq(testERC20.balanceOf(coinbase), 0, "invalid coinbase balance"); + assertEq( + testERC20.balanceOf(data.decodedHeader.globalVariables.coinbase), + 0, + "invalid coinbase balance" + ); assertEq(testERC20.balanceOf(address(quote.prover)), 0, "invalid prover balance"); { @@ -744,7 +781,8 @@ contract RollupTest is DecoderBase, TimeFns { preBlockHash, data.blockHash, bytes32(uint256(42)), - coinbase, + this.getBlobPublicInputs(data.blobInputs), + data.decodedHeader.globalVariables.coinbase, feeAmount ); @@ -752,7 +790,11 @@ contract RollupTest is DecoderBase, TimeFns { uint256 expectedProverReward = Math.mulDiv(expectedReward, quote.basisPointFee, 10_000); uint256 expectedSequencerReward = expectedReward - expectedProverReward; - assertEq(testERC20.balanceOf(coinbase), expectedSequencerReward, "invalid coinbase balance"); + assertEq( + testERC20.balanceOf(data.decodedHeader.globalVariables.coinbase), + expectedSequencerReward, + "invalid coinbase balance" + ); assertEq(testERC20.balanceOf(quote.prover), expectedProverReward, "invalid prover balance"); } } @@ -782,7 +824,20 @@ contract RollupTest is DecoderBase, TimeFns { assertEq(rollup.getProvenBlockNumber(), 0, "Invalid initial proven block number"); (bytes32 preArchive, bytes32 preBlockHash,) = rollup.blocks(0); - _submitEpochProof(rollup, 2, preArchive, data.archive, preBlockHash, data.blockHash, bytes32(0)); + bytes memory blobPublicInputs = abi.encodePacked( + this.getBlobPublicInputs(load("mixed_block_1").block.blobInputs), + this.getBlobPublicInputs(data.blobInputs) + ); + _submitEpochProof( + rollup, + 2, + preArchive, + data.archive, + preBlockHash, + data.blockHash, + bytes32(0), + blobPublicInputs + ); assertEq(rollup.getPendingBlockNumber(), 2, "Invalid pending block number"); assertEq(rollup.getProvenBlockNumber(), 2, "Invalid proven block number"); @@ -804,18 +859,26 @@ contract RollupTest is DecoderBase, TimeFns { txHashes, signatures, data2.body, - abi.encodePacked(data2.decodedHeader.contentCommitment.blobHash, new bytes(112)) + data2.blobInputs ); // Skips proving of block 1 (bytes32 preArchive,,) = rollup.blocks(0); + bytes memory blobPublicInputs = this.getBlobPublicInputs(data1.blobInputs); vm.expectRevert( abi.encodeWithSelector( Errors.Rollup__InvalidPreviousArchive.selector, preArchive, data1.archive ) ); _submitEpochProof( - rollup, 1, data1.archive, data2.archive, data1.archive, data2.archive, bytes32(0) + rollup, + 1, + data1.archive, + data2.archive, + data1.archive, + data2.archive, + bytes32(0), + blobPublicInputs ); assertEq(rollup.getPendingBlockNumber(), 2, "Invalid pending block number"); @@ -850,15 +913,7 @@ contract RollupTest is DecoderBase, TimeFns { } skipBlobCheck(); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidBlockNumber.selector, 1, 0x420)); - rollup.propose( - header, - archive, - data.blockHash, - txHashes, - signatures, - body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) - ); + rollup.propose(header, archive, data.blockHash, txHashes, signatures, body, data.blobInputs); } function testRevertInvalidChainId() public setUpFor("empty_block_1") { @@ -873,15 +928,7 @@ contract RollupTest is DecoderBase, TimeFns { } skipBlobCheck(); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidChainId.selector, 31337, 0x420)); - rollup.propose( - header, - archive, - data.blockHash, - txHashes, - signatures, - body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) - ); + rollup.propose(header, archive, data.blockHash, txHashes, signatures, body, data.blobInputs); } function testRevertInvalidVersion() public setUpFor("empty_block_1") { @@ -896,15 +943,7 @@ contract RollupTest is DecoderBase, TimeFns { } skipBlobCheck(); vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__InvalidVersion.selector, 1, 0x420)); - rollup.propose( - header, - archive, - data.blockHash, - txHashes, - signatures, - body, - abi.encodePacked(data.decodedHeader.contentCommitment.blobHash, new bytes(112)) - ); + rollup.propose(header, archive, data.blockHash, txHashes, signatures, body, data.blobInputs); } function testRevertInvalidTimestamp() public setUpFor("empty_block_1") { @@ -960,7 +999,9 @@ contract RollupTest is DecoderBase, TimeFns { vm.expectRevert( abi.encodeWithSelector(Errors.Rollup__InvalidPreviousArchive.selector, preArchive, wrong) ); - _submitEpochProof(rollup, 1, wrong, data.archive, preBlockHash, data.blockHash, bytes32(0)); + _submitEpochProof( + rollup, 1, wrong, data.archive, preBlockHash, data.blockHash, bytes32(0), new bytes(112) + ); // TODO: Reenable when we setup proper initial block hash // vm.expectRevert( @@ -979,7 +1020,9 @@ contract RollupTest is DecoderBase, TimeFns { vm.expectRevert( abi.encodeWithSelector(Errors.Rollup__InvalidArchive.selector, data.archive, 0xdeadbeef) ); - _submitEpochProof(rollup, 1, preArchive, wrongArchive, preBlockHash, data.blockHash, bytes32(0)); + _submitEpochProof( + rollup, 1, preArchive, wrongArchive, preBlockHash, data.blockHash, bytes32(0), new bytes(112) + ); } function testSubmitProofInvalidBlockHash() public setUpFor("empty_block_1") { @@ -994,7 +1037,40 @@ contract RollupTest is DecoderBase, TimeFns { Errors.Rollup__InvalidBlockHash.selector, data.blockHash, wrongBlockHash ) ); - _submitEpochProof(rollup, 1, preArchive, data.archive, preBlockHash, wrongBlockHash, bytes32(0)); + _submitEpochProof( + rollup, 1, preArchive, data.archive, preBlockHash, wrongBlockHash, bytes32(0), new bytes(112) + ); + } + + function testSubmitProofInvalidBlobPublicInput() public setUpFor("empty_block_1") { + _testBlock("empty_block_1", false); + + DecoderBase.Data memory data = load("empty_block_1").block; + bytes memory blobPublicInputs = this.getBlobPublicInputs(data.blobInputs); + // mess with the data + blobPublicInputs[100] = 0x01; + + (bytes32 preArchive, bytes32 preBlockHash,) = rollup.blocks(0); + bytes32 actualBlobPublicInputsHash = + rollup.blobPublicInputsHashes(data.decodedHeader.globalVariables.blockNumber); + bytes32 wrongBlobPublicInputsHash = this.getBlobPublicInputsHash(blobPublicInputs); + vm.expectRevert( + abi.encodeWithSelector( + Errors.Rollup__InvalidBlobPublicInputsHash.selector, + actualBlobPublicInputsHash, + wrongBlobPublicInputsHash + ) + ); + _submitEpochProof( + rollup, + 1, + preArchive, + data.archive, + preBlockHash, + data.blockHash, + bytes32(0), + blobPublicInputs + ); } function _testBlock(string memory name, bool _submitProof) public { @@ -1005,9 +1081,8 @@ contract RollupTest is DecoderBase, TimeFns { DecoderBase.Full memory full = load(name); bytes memory header = full.block.header; bytes memory body = full.block.body; - bytes memory blobPublicInputs = full.block.blobPublicInputs; + bytes memory blobInputs = full.block.blobInputs; uint32 numTxs = full.block.numTxs; - bytes32[] memory txHashes = new bytes32[](0); Slot slotNumber = Slot.wrap(_slotNumber); @@ -1030,31 +1105,38 @@ contract RollupTest is DecoderBase, TimeFns { { bytes32[] memory blobHashes = new bytes32[](1); - blobHashes[0] = bytes32(blobPublicInputs); + // The below is the blob hash == bytes [1:33] of _blobInput + bytes32 blobHash; + assembly { + blobHash := mload(add(blobInputs, 0x21)) + } + blobHashes[0] = blobHash; vm.blobhashes(blobHashes); } rollup.propose( - header, full.block.archive, full.block.blockHash, txHashes, signatures, body, blobPublicInputs + header, + full.block.archive, + full.block.blockHash, + new bytes32[](0), + signatures, + body, + blobInputs ); - { - // The below is the blob challenge == bytes [32:64] of _blobInput - bytes32 z; - assembly { - z := mload(add(blobPublicInputs, 0x40)) - } - (bytes32 expectedZ,) = - rollup.blobPublicInputs(full.block.decodedHeader.globalVariables.blockNumber); - assertEq(expectedZ, z, "Blob info not stored correctly"); - } - if (_submitProof) { uint256 pre = rollup.getProvenBlockNumber(); (bytes32 preArchive, bytes32 preBlockHash,) = rollup.blocks(pre); _submitEpochProof( - rollup, 1, preArchive, full.block.archive, preBlockHash, full.block.blockHash, bytes32(0) + rollup, + 1, + preArchive, + full.block.archive, + preBlockHash, + full.block.blockHash, + bytes32(0), + this.getBlobPublicInputs(blobInputs) ); assertEq(pre + 1, rollup.getProvenBlockNumber(), "Block not proven"); } @@ -1115,7 +1197,8 @@ contract RollupTest is DecoderBase, TimeFns { bytes32 _endArchive, bytes32 _previousBlockHash, bytes32 _endBlockHash, - bytes32 _proverId + bytes32 _proverId, + bytes memory _blobPublicInputs ) internal { _submitEpochProofWithFee( _rollup, @@ -1125,6 +1208,7 @@ contract RollupTest is DecoderBase, TimeFns { _previousBlockHash, _endBlockHash, _proverId, + _blobPublicInputs, address(0), uint256(0) ); @@ -1138,6 +1222,7 @@ contract RollupTest is DecoderBase, TimeFns { bytes32 _previousBlockHash, bytes32 _endBlockHash, bytes32 _proverId, + bytes memory _blobPublicInputs, address _feeRecipient, uint256 _feeAmount ) internal { @@ -1159,7 +1244,9 @@ contract RollupTest is DecoderBase, TimeFns { bytes memory aggregationObject = ""; bytes memory proof = ""; - _rollup.submitEpochRootProof(_epochSize, args, fees, aggregationObject, proof); + _rollup.submitEpochRootProof( + _epochSize, args, fees, abi.encodePacked(_blobPublicInputs, aggregationObject), proof + ); } function _quoteToSignedQuote(EpochProofQuoteLib.EpochProofQuote memory _quote) diff --git a/l1-contracts/test/decoders/Base.sol b/l1-contracts/test/decoders/Base.sol index 8052d89295b..5de7164a663 100644 --- a/l1-contracts/test/decoders/Base.sol +++ b/l1-contracts/test/decoders/Base.sol @@ -35,7 +35,7 @@ contract DecoderBase is TestBase { struct Data { bytes32 archive; - bytes blobPublicInputs; + bytes blobInputs; bytes32 blockHash; bytes body; DecodedHeader decodedHeader; diff --git a/l1-contracts/test/fixtures/empty_block_1.json b/l1-contracts/test/fixtures/empty_block_1.json index 2424940e594..5d6172d97b6 100644 --- a/l1-contracts/test/fixtures/empty_block_1.json +++ b/l1-contracts/test/fixtures/empty_block_1.json @@ -8,12 +8,12 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x01d1726a7ceffaacdbb4ae00c982f41adf9c8b1f8d30356947a0158535b950e6", - "blockHash": "0x2af4dfb7b51105ef5f9249d79cee9c4f8b690fe22639d4ddee36584def037f5f", + "archive": "0x0608b59639f4b6e991f2192041a0a1a18fdb25c3a9a0da8334a344d4a2d95d25", + "blockHash": "0x23dbfcca3effdce13442bff627b1d1c372380fd4eb58beb596bd43239d8a7bfc", "body": "0x00000000", "decodedHeader": { "contentCommitment": { - "blobHash": "0x000657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014", + "blobHash": "0x001cedbd7ea5309ef9d1d159209835409bf41b6b1802597a52fa70cc82e934d9", "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb", "numTxs": 2 @@ -22,10 +22,10 @@ "blockNumber": 1, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000012", "chainId": 31337, - "timestamp": 1731602726, + "timestamp": 1731775446, "version": 1, - "coinbase": "0xb36b3ce7874e48628d284624ae016291dbe6be66", - "feeRecipient": "0x06ec1ce6aed44ad2c76d1af3c9c4a74b44483c08d500968959219a0f59ca6ee9", + "coinbase": "0x8dce642ee912e07e7686a2c7d8d15a12006bc0ce", + "feeRecipient": "0x14eec7ed2c57101c4f1b2fb7f16fa98b0c509b82c7d1da46e51f56bfc181a319", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -56,9 +56,9 @@ } } }, - "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce1900467779860000000010000000000000000000000000000000000000000000000000000000000000002000657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c44401400089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000101fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000000800c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000067362926b36b3ce7874e48628d284624ae016291dbe6be6606ec1ce6aed44ad2c76d1af3c9c4a74b44483c08d500968959219a0f59ca6ee9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00559d859266edc2d7df71edeae3e24277a0648166a6f822c61c5e7d59181317", - "blobPublicInputs": "0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440140ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb0000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce1900467779860000000010000000000000000000000000000000000000000000000000000000000000002001cedbd7ea5309ef9d1d159209835409bf41b6b1802597a52fa70cc82e934d900089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000101fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000000800c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000010023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001000000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000006738cbd68dce642ee912e07e7686a2c7d8d15a12006bc0ce14eec7ed2c57101c4f1b2fb7f16fa98b0c509b82c7d1da46e51f56bfc181a319000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x008cf42fa316df70efb2c53dbbd265613be250b38603c51a36cdd1de30b61272", + "blobInputs": "0x01010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440140ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb0000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/empty_block_2.json b/l1-contracts/test/fixtures/empty_block_2.json index a1865281507..29ed4095a3b 100644 --- a/l1-contracts/test/fixtures/empty_block_2.json +++ b/l1-contracts/test/fixtures/empty_block_2.json @@ -8,12 +8,12 @@ "l2ToL1Messages": [] }, "block": { - "archive": "0x1bdf6b15eebae67cc6c4ec6b9d2b8edfde444707c5e53cdbc88e2ff86e28feb3", - "blockHash": "0x0222ba7ed40c11d51b8c08e318f590c393ba966583cdf1d028399eb60c368541", + "archive": "0x142d6054dfd797a35b57dc84fd98867584d75e96a7399b7c27f4636e969fd61b", + "blockHash": "0x2db000b1a872480487023e4e8171c608d36f0a7e4e2caad67796e65b520122ca", "body": "0x00000000", "decodedHeader": { "contentCommitment": { - "blobHash": "0x000657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c444014", + "blobHash": "0x001cedbd7ea5309ef9d1d159209835409bf41b6b1802597a52fa70cc82e934d9", "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb", "numTxs": 2 @@ -22,10 +22,10 @@ "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000013", "chainId": 31337, - "timestamp": 1731602750, + "timestamp": 1731775470, "version": 1, - "coinbase": "0xb36b3ce7874e48628d284624ae016291dbe6be66", - "feeRecipient": "0x06ec1ce6aed44ad2c76d1af3c9c4a74b44483c08d500968959219a0f59ca6ee9", + "coinbase": "0x8dce642ee912e07e7686a2c7d8d15a12006bc0ce", + "feeRecipient": "0x14eec7ed2c57101c4f1b2fb7f16fa98b0c509b82c7d1da46e51f56bfc181a319", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -33,7 +33,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x01d1726a7ceffaacdbb4ae00c982f41adf9c8b1f8d30356947a0158535b950e6" + "root": "0x0608b59639f4b6e991f2192041a0a1a18fdb25c3a9a0da8334a344d4a2d95d25" }, "stateReference": { "l1ToL2MessageTree": { @@ -56,9 +56,9 @@ } } }, - "header": "0x01d1726a7ceffaacdbb4ae00c982f41adf9c8b1f8d30356947a0158535b950e6000000020000000000000000000000000000000000000000000000000000000000000002000657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c44401400089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000201fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000001000c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000006736293eb36b3ce7874e48628d284624ae016291dbe6be6606ec1ce6aed44ad2c76d1af3c9c4a74b44483c08d500968959219a0f59ca6ee9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00bf101079d778b7f8959ba97a76d1c6c35aa595ac01736dc0ef877352230aed", - "blobPublicInputs": "0x010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440140ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb0000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "header": "0x0608b59639f4b6e991f2192041a0a1a18fdb25c3a9a0da8334a344d4a2d95d25000000020000000000000000000000000000000000000000000000000000000000000002001cedbd7ea5309ef9d1d159209835409bf41b6b1802597a52fa70cc82e934d900089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb2e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d6000000201fd848aa69e1633722fe249a5b7f53b094f1c9cef9f5c694b073fd1cc5850dfb000001000c499b373a1f0fe1b510a63563546d2d39e206895056a5af0143c5f30d6390730000018023c08a6b1297210c5e24c76b9a936250a1ce2721576c26ea797c7ec35f9e46a9000001800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013000000000000000000000000000000000000000000000000000000006738cbee8dce642ee912e07e7686a2c7d8d15a12006bc0ce14eec7ed2c57101c4f1b2fb7f16fa98b0c509b82c7d1da46e51f56bfc181a319000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x002f52b85580ed695df034d3a102c017c8e9a2f7e817e94aa5ebf12763fd5b96", + "blobInputs": "0x01010657f37554c781402a22917dee2f75def7ab966d7b770905398eba3c4440140ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb0000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "numTxs": 0 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_1.json b/l1-contracts/test/fixtures/mixed_block_1.json index f7f314548fd..8fcae6dab35 100644 --- a/l1-contracts/test/fixtures/mixed_block_1.json +++ b/l1-contracts/test/fixtures/mixed_block_1.json @@ -58,12 +58,12 @@ ] }, "block": { - "archive": "0x0c8761d01984809bc7d2b22ad95919a63ecb26627391e6cc96e4c25db3dadc94", - "blockHash": "0x2a62a014c30e82cc1a2af23cec073cc894cfb50159de68fac223466d67ad9f3e", + "archive": "0x1c33efe9cb9b002061f68be15b0c7ccc5fe4293ba4e1e6777862c2710ad8f6ee", + "blockHash": "0x2d9d1aaed2a34df77745733b16da3408b22c154dd849c26374a6cc5d4d319426", "body": "0x00000004000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004100100000000000000000000000000000000000000000000000000000000000410020000000000000000000000000000000000000000000000000000000000041003000000000000000000000000000000000000000000000000000000000004100400000000000000000000000000000000000000000000000000000000000410050000000000000000000000000000000000000000000000000000000000041006000000000000000000000000000000000000000000000000000000000004100700000000000000000000000000000000000000000000000000000000000410080000000000000000000000000000000000000000000000000000000000041009000000000000000000000000000000000000000000000000000000000004100a000000000000000000000000000000000000000000000000000000000004100b000000000000000000000000000000000000000000000000000000000004100c000000000000000000000000000000000000000000000000000000000004100d000000000000000000000000000000000000000000000000000000000004100e000000000000000000000000000000000000000000000000000000000004100f0000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004101100000000000000000000000000000000000000000000000000000000000410120000000000000000000000000000000000000000000000000000000000041013000000000000000000000000000000000000000000000000000000000004101400000000000000000000000000000000000000000000000000000000000410150000000000000000000000000000000000000000000000000000000000041016000000000000000000000000000000000000000000000000000000000004101700000000000000000000000000000000000000000000000000000000000410180000000000000000000000000000000000000000000000000000000000041019000000000000000000000000000000000000000000000000000000000004101a000000000000000000000000000000000000000000000000000000000004101b000000000000000000000000000000000000000000000000000000000004101c000000000000000000000000000000000000000000000000000000000004101d000000000000000000000000000000000000000000000000000000000004101e000000000000000000000000000000000000000000000000000000000004101f0000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004102100000000000000000000000000000000000000000000000000000000000410220000000000000000000000000000000000000000000000000000000000041023000000000000000000000000000000000000000000000000000000000004102400000000000000000000000000000000000000000000000000000000000410250000000000000000000000000000000000000000000000000000000000041026000000000000000000000000000000000000000000000000000000000004102700000000000000000000000000000000000000000000000000000000000410280000000000000000000000000000000000000000000000000000000000041029000000000000000000000000000000000000000000000000000000000004102a000000000000000000000000000000000000000000000000000000000004102b000000000000000000000000000000000000000000000000000000000004102c000000000000000000000000000000000000000000000000000000000004102d000000000000000000000000000000000000000000000000000000000004102e000000000000000000000000000000000000000000000000000000000004102f0000000000000000000000000000000000000000000000000000000000041030000000000000000000000000000000000000000000000000000000000004103100000000000000000000000000000000000000000000000000000000000410320000000000000000000000000000000000000000000000000000000000041033000000000000000000000000000000000000000000000000000000000004103400000000000000000000000000000000000000000000000000000000000410350000000000000000000000000000000000000000000000000000000000041036000000000000000000000000000000000000000000000000000000000004103700000000000000000000000000000000000000000000000000000000000410380000000000000000000000000000000000000000000000000000000000041039000000000000000000000000000000000000000000000000000000000004103a000000000000000000000000000000000000000000000000000000000004103b000000000000000000000000000000000000000000000000000000000004103c000000000000000000000000000000000000000000000000000000000004103d000000000000000000000000000000000000000000000000000000000004103e000000000000000000000000000000000000000000000000000000000004103f3f0000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004110100000000000000000000000000000000000000000000000000000000000411020000000000000000000000000000000000000000000000000000000000041103000000000000000000000000000000000000000000000000000000000004110400000000000000000000000000000000000000000000000000000000000411050000000000000000000000000000000000000000000000000000000000041106000000000000000000000000000000000000000000000000000000000004110700000000000000000000000000000000000000000000000000000000000411080000000000000000000000000000000000000000000000000000000000041109000000000000000000000000000000000000000000000000000000000004110a000000000000000000000000000000000000000000000000000000000004110b000000000000000000000000000000000000000000000000000000000004110c000000000000000000000000000000000000000000000000000000000004110d000000000000000000000000000000000000000000000000000000000004110e000000000000000000000000000000000000000000000000000000000004110f0000000000000000000000000000000000000000000000000000000000041110000000000000000000000000000000000000000000000000000000000004111100000000000000000000000000000000000000000000000000000000000411120000000000000000000000000000000000000000000000000000000000041113000000000000000000000000000000000000000000000000000000000004111400000000000000000000000000000000000000000000000000000000000411150000000000000000000000000000000000000000000000000000000000041116000000000000000000000000000000000000000000000000000000000004111700000000000000000000000000000000000000000000000000000000000411180000000000000000000000000000000000000000000000000000000000041119000000000000000000000000000000000000000000000000000000000004111a000000000000000000000000000000000000000000000000000000000004111b000000000000000000000000000000000000000000000000000000000004111c000000000000000000000000000000000000000000000000000000000004111d000000000000000000000000000000000000000000000000000000000004111e000000000000000000000000000000000000000000000000000000000004111f0000000000000000000000000000000000000000000000000000000000041120000000000000000000000000000000000000000000000000000000000004112100000000000000000000000000000000000000000000000000000000000411220000000000000000000000000000000000000000000000000000000000041123000000000000000000000000000000000000000000000000000000000004112400000000000000000000000000000000000000000000000000000000000411250000000000000000000000000000000000000000000000000000000000041126000000000000000000000000000000000000000000000000000000000004112700000000000000000000000000000000000000000000000000000000000411280000000000000000000000000000000000000000000000000000000000041129000000000000000000000000000000000000000000000000000000000004112a000000000000000000000000000000000000000000000000000000000004112b000000000000000000000000000000000000000000000000000000000004112c000000000000000000000000000000000000000000000000000000000004112d000000000000000000000000000000000000000000000000000000000004112e000000000000000000000000000000000000000000000000000000000004112f0000000000000000000000000000000000000000000000000000000000041130000000000000000000000000000000000000000000000000000000000004113100000000000000000000000000000000000000000000000000000000000411320000000000000000000000000000000000000000000000000000000000041133000000000000000000000000000000000000000000000000000000000004113400000000000000000000000000000000000000000000000000000000000411350000000000000000000000000000000000000000000000000000000000041136000000000000000000000000000000000000000000000000000000000004113700000000000000000000000000000000000000000000000000000000000411380000000000000000000000000000000000000000000000000000000000041139000000000000000000000000000000000000000000000000000000000004113a000000000000000000000000000000000000000000000000000000000004113b000000000000000000000000000000000000000000000000000000000004113c000000000000000000000000000000000000000000000000000000000004113d000000000000000000000000000000000000000000000000000000000004113e080097a6ec570e9b8e257647c9c74c5ad3edc57ca5ef6ae44d80b3c30d1d99b9b300ce48ec41d1edde0066fab553a456ae2f380d14fa8f956af1fb0217513a598900619ff12eaf97f63aa2a2311de3b6571a7b880a5247cb33b6a74787bf3f9bd5007854a2fad4e1801c6404394bf3d37ab08c135ea38a1974242e39a21273685f000f55796e72957a819e68a22e8602d73c3ba3718a5a4bd92b80b0aa444b182a00788b6e9874fb040ee679a7fae257190099a605229b948334e54a57739535d4004f1658ee3c1a91627e5d72f5a731f0796299df82ab41e72c88eee0c82fa85e003ee802add96628c693ed71afa9908138ba5a6fbf0a5f29a9c74e4e42aba6713f0000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042001000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042002000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042003000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042004000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042005000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420060000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004200700000000000000000000000000000000000000000000000000000000000420110000000000000000000000000000000000000000000000000000000000042008000000000000000000000000000000000000000000000000000000000004201200000000000000000000000000000000000000000000000000000000000420090000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042016000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042017000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042011000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042012000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420160000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004201700000000000000000000000000000000000000000000000000000000000420210000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004202200000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042026000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042027000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042021000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042022000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420260000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004202700000000000000000000000000000000000000000000000000000000000420310000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004203200000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042036000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042037000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042031000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042032000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004203f00000000000000000000000000000000000000000000000000000000000420360000000000000000000000000000000000000000000000000000000000042040000000000000000000000000000000000000000000000000000000000004203700000000000000000000000000000000000000000000000000000000000420410000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004204200000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042043000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042044000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042045000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042046000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042047000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008100100000000000000000000000000000000000000000000000000000000000810020000000000000000000000000000000000000000000000000000000000081003000000000000000000000000000000000000000000000000000000000008100400000000000000000000000000000000000000000000000000000000000810050000000000000000000000000000000000000000000000000000000000081006000000000000000000000000000000000000000000000000000000000008100700000000000000000000000000000000000000000000000000000000000810080000000000000000000000000000000000000000000000000000000000081009000000000000000000000000000000000000000000000000000000000008100a000000000000000000000000000000000000000000000000000000000008100b000000000000000000000000000000000000000000000000000000000008100c000000000000000000000000000000000000000000000000000000000008100d000000000000000000000000000000000000000000000000000000000008100e000000000000000000000000000000000000000000000000000000000008100f0000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008101100000000000000000000000000000000000000000000000000000000000810120000000000000000000000000000000000000000000000000000000000081013000000000000000000000000000000000000000000000000000000000008101400000000000000000000000000000000000000000000000000000000000810150000000000000000000000000000000000000000000000000000000000081016000000000000000000000000000000000000000000000000000000000008101700000000000000000000000000000000000000000000000000000000000810180000000000000000000000000000000000000000000000000000000000081019000000000000000000000000000000000000000000000000000000000008101a000000000000000000000000000000000000000000000000000000000008101b000000000000000000000000000000000000000000000000000000000008101c000000000000000000000000000000000000000000000000000000000008101d000000000000000000000000000000000000000000000000000000000008101e000000000000000000000000000000000000000000000000000000000008101f0000000000000000000000000000000000000000000000000000000000081020000000000000000000000000000000000000000000000000000000000008102100000000000000000000000000000000000000000000000000000000000810220000000000000000000000000000000000000000000000000000000000081023000000000000000000000000000000000000000000000000000000000008102400000000000000000000000000000000000000000000000000000000000810250000000000000000000000000000000000000000000000000000000000081026000000000000000000000000000000000000000000000000000000000008102700000000000000000000000000000000000000000000000000000000000810280000000000000000000000000000000000000000000000000000000000081029000000000000000000000000000000000000000000000000000000000008102a000000000000000000000000000000000000000000000000000000000008102b000000000000000000000000000000000000000000000000000000000008102c000000000000000000000000000000000000000000000000000000000008102d000000000000000000000000000000000000000000000000000000000008102e000000000000000000000000000000000000000000000000000000000008102f0000000000000000000000000000000000000000000000000000000000081030000000000000000000000000000000000000000000000000000000000008103100000000000000000000000000000000000000000000000000000000000810320000000000000000000000000000000000000000000000000000000000081033000000000000000000000000000000000000000000000000000000000008103400000000000000000000000000000000000000000000000000000000000810350000000000000000000000000000000000000000000000000000000000081036000000000000000000000000000000000000000000000000000000000008103700000000000000000000000000000000000000000000000000000000000810380000000000000000000000000000000000000000000000000000000000081039000000000000000000000000000000000000000000000000000000000008103a000000000000000000000000000000000000000000000000000000000008103b000000000000000000000000000000000000000000000000000000000008103c000000000000000000000000000000000000000000000000000000000008103d000000000000000000000000000000000000000000000000000000000008103e000000000000000000000000000000000000000000000000000000000008103f3f0000000000000000000000000000000000000000000000000000000000081100000000000000000000000000000000000000000000000000000000000008110100000000000000000000000000000000000000000000000000000000000811020000000000000000000000000000000000000000000000000000000000081103000000000000000000000000000000000000000000000000000000000008110400000000000000000000000000000000000000000000000000000000000811050000000000000000000000000000000000000000000000000000000000081106000000000000000000000000000000000000000000000000000000000008110700000000000000000000000000000000000000000000000000000000000811080000000000000000000000000000000000000000000000000000000000081109000000000000000000000000000000000000000000000000000000000008110a000000000000000000000000000000000000000000000000000000000008110b000000000000000000000000000000000000000000000000000000000008110c000000000000000000000000000000000000000000000000000000000008110d000000000000000000000000000000000000000000000000000000000008110e000000000000000000000000000000000000000000000000000000000008110f0000000000000000000000000000000000000000000000000000000000081110000000000000000000000000000000000000000000000000000000000008111100000000000000000000000000000000000000000000000000000000000811120000000000000000000000000000000000000000000000000000000000081113000000000000000000000000000000000000000000000000000000000008111400000000000000000000000000000000000000000000000000000000000811150000000000000000000000000000000000000000000000000000000000081116000000000000000000000000000000000000000000000000000000000008111700000000000000000000000000000000000000000000000000000000000811180000000000000000000000000000000000000000000000000000000000081119000000000000000000000000000000000000000000000000000000000008111a000000000000000000000000000000000000000000000000000000000008111b000000000000000000000000000000000000000000000000000000000008111c000000000000000000000000000000000000000000000000000000000008111d000000000000000000000000000000000000000000000000000000000008111e000000000000000000000000000000000000000000000000000000000008111f0000000000000000000000000000000000000000000000000000000000081120000000000000000000000000000000000000000000000000000000000008112100000000000000000000000000000000000000000000000000000000000811220000000000000000000000000000000000000000000000000000000000081123000000000000000000000000000000000000000000000000000000000008112400000000000000000000000000000000000000000000000000000000000811250000000000000000000000000000000000000000000000000000000000081126000000000000000000000000000000000000000000000000000000000008112700000000000000000000000000000000000000000000000000000000000811280000000000000000000000000000000000000000000000000000000000081129000000000000000000000000000000000000000000000000000000000008112a000000000000000000000000000000000000000000000000000000000008112b000000000000000000000000000000000000000000000000000000000008112c000000000000000000000000000000000000000000000000000000000008112d000000000000000000000000000000000000000000000000000000000008112e000000000000000000000000000000000000000000000000000000000008112f0000000000000000000000000000000000000000000000000000000000081130000000000000000000000000000000000000000000000000000000000008113100000000000000000000000000000000000000000000000000000000000811320000000000000000000000000000000000000000000000000000000000081133000000000000000000000000000000000000000000000000000000000008113400000000000000000000000000000000000000000000000000000000000811350000000000000000000000000000000000000000000000000000000000081136000000000000000000000000000000000000000000000000000000000008113700000000000000000000000000000000000000000000000000000000000811380000000000000000000000000000000000000000000000000000000000081139000000000000000000000000000000000000000000000000000000000008113a000000000000000000000000000000000000000000000000000000000008113b000000000000000000000000000000000000000000000000000000000008113c000000000000000000000000000000000000000000000000000000000008113d000000000000000000000000000000000000000000000000000000000008113e08003c0472260790b0bdfb8ae4dc4d437e7686b73643f2198970d84e1059a5f13500bfd46275a318e438726ff2765ae154b63ab8a0daebcbed668a5f58a0e63dc1007906b9418dc758c6b4f8454c69baa48b7889b6b511d707abe8e2cb8f7c397300aeb60c4d65a44f122e58bf9565dfe2024b3ae654d5cf2e47ecb035d53c927000bf82e8cda20345f37bbb1de3932172324b57f0b98be483392697b168e3bba8000fb4bbad884ef30edf68e45a6cf2733fcf50310c69d7c1432b29af2c0aa8040023e1622d27fee3b4a40ab975ae0eb2e31619ef3dc76eb858f7fddb6a056131004689cd7007daf98dd3218b839b8e6a29f957154347b391fdb376bd0b344be23f0000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082001000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082002000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082003000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082004000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082005000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820060000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008200700000000000000000000000000000000000000000000000000000000000820110000000000000000000000000000000000000000000000000000000000082008000000000000000000000000000000000000000000000000000000000008201200000000000000000000000000000000000000000000000000000000000820090000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082016000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082017000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082011000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082012000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820160000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008201700000000000000000000000000000000000000000000000000000000000820210000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008202200000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082026000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082027000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082021000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082022000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820260000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008202700000000000000000000000000000000000000000000000000000000000820310000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008203200000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082036000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082037000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082031000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082032000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008203e0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008203f00000000000000000000000000000000000000000000000000000000000820360000000000000000000000000000000000000000000000000000000000082040000000000000000000000000000000000000000000000000000000000008203700000000000000000000000000000000000000000000000000000000000820410000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008204200000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082043000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082044000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082045000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082046000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082047000000000000000000000000000000000000000000000000000000000008203e00000000000000000000000000000000000000000000000000000000000820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c100100000000000000000000000000000000000000000000000000000000000c100200000000000000000000000000000000000000000000000000000000000c100300000000000000000000000000000000000000000000000000000000000c100400000000000000000000000000000000000000000000000000000000000c100500000000000000000000000000000000000000000000000000000000000c100600000000000000000000000000000000000000000000000000000000000c100700000000000000000000000000000000000000000000000000000000000c100800000000000000000000000000000000000000000000000000000000000c100900000000000000000000000000000000000000000000000000000000000c100a00000000000000000000000000000000000000000000000000000000000c100b00000000000000000000000000000000000000000000000000000000000c100c00000000000000000000000000000000000000000000000000000000000c100d00000000000000000000000000000000000000000000000000000000000c100e00000000000000000000000000000000000000000000000000000000000c100f00000000000000000000000000000000000000000000000000000000000c101000000000000000000000000000000000000000000000000000000000000c101100000000000000000000000000000000000000000000000000000000000c101200000000000000000000000000000000000000000000000000000000000c101300000000000000000000000000000000000000000000000000000000000c101400000000000000000000000000000000000000000000000000000000000c101500000000000000000000000000000000000000000000000000000000000c101600000000000000000000000000000000000000000000000000000000000c101700000000000000000000000000000000000000000000000000000000000c101800000000000000000000000000000000000000000000000000000000000c101900000000000000000000000000000000000000000000000000000000000c101a00000000000000000000000000000000000000000000000000000000000c101b00000000000000000000000000000000000000000000000000000000000c101c00000000000000000000000000000000000000000000000000000000000c101d00000000000000000000000000000000000000000000000000000000000c101e00000000000000000000000000000000000000000000000000000000000c101f00000000000000000000000000000000000000000000000000000000000c102000000000000000000000000000000000000000000000000000000000000c102100000000000000000000000000000000000000000000000000000000000c102200000000000000000000000000000000000000000000000000000000000c102300000000000000000000000000000000000000000000000000000000000c102400000000000000000000000000000000000000000000000000000000000c102500000000000000000000000000000000000000000000000000000000000c102600000000000000000000000000000000000000000000000000000000000c102700000000000000000000000000000000000000000000000000000000000c102800000000000000000000000000000000000000000000000000000000000c102900000000000000000000000000000000000000000000000000000000000c102a00000000000000000000000000000000000000000000000000000000000c102b00000000000000000000000000000000000000000000000000000000000c102c00000000000000000000000000000000000000000000000000000000000c102d00000000000000000000000000000000000000000000000000000000000c102e00000000000000000000000000000000000000000000000000000000000c102f00000000000000000000000000000000000000000000000000000000000c103000000000000000000000000000000000000000000000000000000000000c103100000000000000000000000000000000000000000000000000000000000c103200000000000000000000000000000000000000000000000000000000000c103300000000000000000000000000000000000000000000000000000000000c103400000000000000000000000000000000000000000000000000000000000c103500000000000000000000000000000000000000000000000000000000000c103600000000000000000000000000000000000000000000000000000000000c103700000000000000000000000000000000000000000000000000000000000c103800000000000000000000000000000000000000000000000000000000000c103900000000000000000000000000000000000000000000000000000000000c103a00000000000000000000000000000000000000000000000000000000000c103b00000000000000000000000000000000000000000000000000000000000c103c00000000000000000000000000000000000000000000000000000000000c103d00000000000000000000000000000000000000000000000000000000000c103e00000000000000000000000000000000000000000000000000000000000c103f3f00000000000000000000000000000000000000000000000000000000000c110000000000000000000000000000000000000000000000000000000000000c110100000000000000000000000000000000000000000000000000000000000c110200000000000000000000000000000000000000000000000000000000000c110300000000000000000000000000000000000000000000000000000000000c110400000000000000000000000000000000000000000000000000000000000c110500000000000000000000000000000000000000000000000000000000000c110600000000000000000000000000000000000000000000000000000000000c110700000000000000000000000000000000000000000000000000000000000c110800000000000000000000000000000000000000000000000000000000000c110900000000000000000000000000000000000000000000000000000000000c110a00000000000000000000000000000000000000000000000000000000000c110b00000000000000000000000000000000000000000000000000000000000c110c00000000000000000000000000000000000000000000000000000000000c110d00000000000000000000000000000000000000000000000000000000000c110e00000000000000000000000000000000000000000000000000000000000c110f00000000000000000000000000000000000000000000000000000000000c111000000000000000000000000000000000000000000000000000000000000c111100000000000000000000000000000000000000000000000000000000000c111200000000000000000000000000000000000000000000000000000000000c111300000000000000000000000000000000000000000000000000000000000c111400000000000000000000000000000000000000000000000000000000000c111500000000000000000000000000000000000000000000000000000000000c111600000000000000000000000000000000000000000000000000000000000c111700000000000000000000000000000000000000000000000000000000000c111800000000000000000000000000000000000000000000000000000000000c111900000000000000000000000000000000000000000000000000000000000c111a00000000000000000000000000000000000000000000000000000000000c111b00000000000000000000000000000000000000000000000000000000000c111c00000000000000000000000000000000000000000000000000000000000c111d00000000000000000000000000000000000000000000000000000000000c111e00000000000000000000000000000000000000000000000000000000000c111f00000000000000000000000000000000000000000000000000000000000c112000000000000000000000000000000000000000000000000000000000000c112100000000000000000000000000000000000000000000000000000000000c112200000000000000000000000000000000000000000000000000000000000c112300000000000000000000000000000000000000000000000000000000000c112400000000000000000000000000000000000000000000000000000000000c112500000000000000000000000000000000000000000000000000000000000c112600000000000000000000000000000000000000000000000000000000000c112700000000000000000000000000000000000000000000000000000000000c112800000000000000000000000000000000000000000000000000000000000c112900000000000000000000000000000000000000000000000000000000000c112a00000000000000000000000000000000000000000000000000000000000c112b00000000000000000000000000000000000000000000000000000000000c112c00000000000000000000000000000000000000000000000000000000000c112d00000000000000000000000000000000000000000000000000000000000c112e00000000000000000000000000000000000000000000000000000000000c112f00000000000000000000000000000000000000000000000000000000000c113000000000000000000000000000000000000000000000000000000000000c113100000000000000000000000000000000000000000000000000000000000c113200000000000000000000000000000000000000000000000000000000000c113300000000000000000000000000000000000000000000000000000000000c113400000000000000000000000000000000000000000000000000000000000c113500000000000000000000000000000000000000000000000000000000000c113600000000000000000000000000000000000000000000000000000000000c113700000000000000000000000000000000000000000000000000000000000c113800000000000000000000000000000000000000000000000000000000000c113900000000000000000000000000000000000000000000000000000000000c113a00000000000000000000000000000000000000000000000000000000000c113b00000000000000000000000000000000000000000000000000000000000c113c00000000000000000000000000000000000000000000000000000000000c113d00000000000000000000000000000000000000000000000000000000000c113e0800f8029be42ec3f25204907ca981fb71e5b357093eb5db10fc01ca98a4e4154c0030e13d351a5bf1d5a040e82a163ca57017f39162693f85c571e441e36d702d00a550ae0f39f977d9473d6de1be3232fc68ed0c4a601d53542148695102cfc9005580bc65e4bff9c8fffa64db02c0fa6af14d9d26fd962f4c5904cbd3ddec2500758c4a0d43dfec788b2f580877c4f473adec8f168ea24424f2600e4eb4916f00342602bf90d10f8ca8e582a894dcc4c02bb89fe458532e0c632b53bae54b4d00ca43ab78ab834337e9964d84a0674c9adabdca140539c5a6bc96e0ba9a51f6004ffbfd91be292a7c6a0e255e50caa156ac2d628b40ad2128c4ab63a92d8a1c3f00000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c200100000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c200200000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c200300000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c200400000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c200500000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c200600000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c200700000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c200800000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c200900000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c203f00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c204000000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c204100000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c204200000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c204300000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c204400000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c204500000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c204600000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c204700000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010100100000000000000000000000000000000000000000000000000000000001010020000000000000000000000000000000000000000000000000000000000101003000000000000000000000000000000000000000000000000000000000010100400000000000000000000000000000000000000000000000000000000001010050000000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000010100700000000000000000000000000000000000000000000000000000000001010080000000000000000000000000000000000000000000000000000000000101009000000000000000000000000000000000000000000000000000000000010100a000000000000000000000000000000000000000000000000000000000010100b000000000000000000000000000000000000000000000000000000000010100c000000000000000000000000000000000000000000000000000000000010100d000000000000000000000000000000000000000000000000000000000010100e000000000000000000000000000000000000000000000000000000000010100f0000000000000000000000000000000000000000000000000000000000101010000000000000000000000000000000000000000000000000000000000010101100000000000000000000000000000000000000000000000000000000001010120000000000000000000000000000000000000000000000000000000000101013000000000000000000000000000000000000000000000000000000000010101400000000000000000000000000000000000000000000000000000000001010150000000000000000000000000000000000000000000000000000000000101016000000000000000000000000000000000000000000000000000000000010101700000000000000000000000000000000000000000000000000000000001010180000000000000000000000000000000000000000000000000000000000101019000000000000000000000000000000000000000000000000000000000010101a000000000000000000000000000000000000000000000000000000000010101b000000000000000000000000000000000000000000000000000000000010101c000000000000000000000000000000000000000000000000000000000010101d000000000000000000000000000000000000000000000000000000000010101e000000000000000000000000000000000000000000000000000000000010101f0000000000000000000000000000000000000000000000000000000000101020000000000000000000000000000000000000000000000000000000000010102100000000000000000000000000000000000000000000000000000000001010220000000000000000000000000000000000000000000000000000000000101023000000000000000000000000000000000000000000000000000000000010102400000000000000000000000000000000000000000000000000000000001010250000000000000000000000000000000000000000000000000000000000101026000000000000000000000000000000000000000000000000000000000010102700000000000000000000000000000000000000000000000000000000001010280000000000000000000000000000000000000000000000000000000000101029000000000000000000000000000000000000000000000000000000000010102a000000000000000000000000000000000000000000000000000000000010102b000000000000000000000000000000000000000000000000000000000010102c000000000000000000000000000000000000000000000000000000000010102d000000000000000000000000000000000000000000000000000000000010102e000000000000000000000000000000000000000000000000000000000010102f0000000000000000000000000000000000000000000000000000000000101030000000000000000000000000000000000000000000000000000000000010103100000000000000000000000000000000000000000000000000000000001010320000000000000000000000000000000000000000000000000000000000101033000000000000000000000000000000000000000000000000000000000010103400000000000000000000000000000000000000000000000000000000001010350000000000000000000000000000000000000000000000000000000000101036000000000000000000000000000000000000000000000000000000000010103700000000000000000000000000000000000000000000000000000000001010380000000000000000000000000000000000000000000000000000000000101039000000000000000000000000000000000000000000000000000000000010103a000000000000000000000000000000000000000000000000000000000010103b000000000000000000000000000000000000000000000000000000000010103c000000000000000000000000000000000000000000000000000000000010103d000000000000000000000000000000000000000000000000000000000010103e000000000000000000000000000000000000000000000000000000000010103f3f0000000000000000000000000000000000000000000000000000000000101100000000000000000000000000000000000000000000000000000000000010110100000000000000000000000000000000000000000000000000000000001011020000000000000000000000000000000000000000000000000000000000101103000000000000000000000000000000000000000000000000000000000010110400000000000000000000000000000000000000000000000000000000001011050000000000000000000000000000000000000000000000000000000000101106000000000000000000000000000000000000000000000000000000000010110700000000000000000000000000000000000000000000000000000000001011080000000000000000000000000000000000000000000000000000000000101109000000000000000000000000000000000000000000000000000000000010110a000000000000000000000000000000000000000000000000000000000010110b000000000000000000000000000000000000000000000000000000000010110c000000000000000000000000000000000000000000000000000000000010110d000000000000000000000000000000000000000000000000000000000010110e000000000000000000000000000000000000000000000000000000000010110f0000000000000000000000000000000000000000000000000000000000101110000000000000000000000000000000000000000000000000000000000010111100000000000000000000000000000000000000000000000000000000001011120000000000000000000000000000000000000000000000000000000000101113000000000000000000000000000000000000000000000000000000000010111400000000000000000000000000000000000000000000000000000000001011150000000000000000000000000000000000000000000000000000000000101116000000000000000000000000000000000000000000000000000000000010111700000000000000000000000000000000000000000000000000000000001011180000000000000000000000000000000000000000000000000000000000101119000000000000000000000000000000000000000000000000000000000010111a000000000000000000000000000000000000000000000000000000000010111b000000000000000000000000000000000000000000000000000000000010111c000000000000000000000000000000000000000000000000000000000010111d000000000000000000000000000000000000000000000000000000000010111e000000000000000000000000000000000000000000000000000000000010111f0000000000000000000000000000000000000000000000000000000000101120000000000000000000000000000000000000000000000000000000000010112100000000000000000000000000000000000000000000000000000000001011220000000000000000000000000000000000000000000000000000000000101123000000000000000000000000000000000000000000000000000000000010112400000000000000000000000000000000000000000000000000000000001011250000000000000000000000000000000000000000000000000000000000101126000000000000000000000000000000000000000000000000000000000010112700000000000000000000000000000000000000000000000000000000001011280000000000000000000000000000000000000000000000000000000000101129000000000000000000000000000000000000000000000000000000000010112a000000000000000000000000000000000000000000000000000000000010112b000000000000000000000000000000000000000000000000000000000010112c000000000000000000000000000000000000000000000000000000000010112d000000000000000000000000000000000000000000000000000000000010112e000000000000000000000000000000000000000000000000000000000010112f0000000000000000000000000000000000000000000000000000000000101130000000000000000000000000000000000000000000000000000000000010113100000000000000000000000000000000000000000000000000000000001011320000000000000000000000000000000000000000000000000000000000101133000000000000000000000000000000000000000000000000000000000010113400000000000000000000000000000000000000000000000000000000001011350000000000000000000000000000000000000000000000000000000000101136000000000000000000000000000000000000000000000000000000000010113700000000000000000000000000000000000000000000000000000000001011380000000000000000000000000000000000000000000000000000000000101139000000000000000000000000000000000000000000000000000000000010113a000000000000000000000000000000000000000000000000000000000010113b000000000000000000000000000000000000000000000000000000000010113c000000000000000000000000000000000000000000000000000000000010113d000000000000000000000000000000000000000000000000000000000010113e080099145b6c0d32753835121f8b271186d01236948a4622ce78a98347fcfc98390085277a27c6acbd5ffc4c19cd65fc30056999e9bec36998f753132db0ff8e2300f3cf77a7261759ebd5f4149f6ad56746f4499cfcd4adf27a1d373f77da64d5009bc6e0e994a23cde8c95b90c1acc1b4a480c6599d1df2c3f9f6e76f3d1aff200d7a1c4a2700dacaaf07f1f0ff33837bdbabcf0b9ace17efabe0761708c4bb900dbeb8e96d14f21e57d5786b6d6ae7e5ddb1bb35935c0fb246d4bdbca62e02c00fbf12b5e0df6223b801088798e4e04d2a92ffe9a11639b7f0ce314e3412a8000d796e0724de03b796ba77069fcd6cf921e566f3aed15eb3e77258add74e9ff3f0000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102001000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102002000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102003000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102004000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102005000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020060000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010200700000000000000000000000000000000000000000000000000000000001020110000000000000000000000000000000000000000000000000000000000102008000000000000000000000000000000000000000000000000000000000010201200000000000000000000000000000000000000000000000000000000001020090000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102016000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102017000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102011000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102012000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020160000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010201700000000000000000000000000000000000000000000000000000000001020210000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010202200000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102026000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102027000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102021000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102022000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020260000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010202700000000000000000000000000000000000000000000000000000000001020310000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010203200000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102036000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102037000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102031000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102032000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010203f00000000000000000000000000000000000000000000000000000000001020360000000000000000000000000000000000000000000000000000000000102040000000000000000000000000000000000000000000000000000000000010203700000000000000000000000000000000000000000000000000000000001020410000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010204200000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102043000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102044000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102045000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102046000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102047000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "decodedHeader": { "contentCommitment": { - "blobHash": "0x00cb2643c794ffd2835b698dffc25f63cfff60717970cd3e7f7c0fb91f8303b8", + "blobHash": "0x00476e8bde67f5103417638177f69bafaab0a230f87b856043fe8fc0c8643f5f", "inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c", "outHash": "0x000ca4a4610ad22c97c9161cedcf01faa3619f1b85457f1627d09627b71903a6", "numTxs": 4 @@ -72,10 +72,10 @@ "blockNumber": 1, "slotNumber": "0x000000000000000000000000000000000000000000000000000000000000001a", "chainId": 31337, - "timestamp": 1731601946, + "timestamp": 1731774666, "version": 1, - "coinbase": "0x04197076bf00abeee6a831983ef8302441add4ef", - "feeRecipient": "0x06b0da1b672bf6d9380e9553ff0985441795d437cdb5b685aba840453f8f46b0", + "coinbase": "0xcf4026defdbcf6d380561d2efbd56b77bb010b88", + "feeRecipient": "0x1d8e356ffb1a70658c67ac17b27be96faeab7707331b882e25a7a79c087ddcd1", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -106,9 +106,9 @@ } } }, - "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce190046777986000000001000000000000000000000000000000000000000000000000000000000000000400cb2643c794ffd2835b698dffc25f63cfff60717970cd3e7f7c0fb91f8303b800089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c000ca4a4610ad22c97c9161cedcf01faa3619f1b85457f1627d09627b71903a62e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d60000001000553ea03210e12bf95ed15f0105108f39db784d318cfe9b52cba413618711ce000001001d52eeaaacb445d9193d29e0df8f0ad4bf69bc457fe955b8e05b48ae3fdc3b3f00000180160cf8d0dbcc7b6a69aede9d89adb66554ba8054d9944b6ab5475e155e8f73d4000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000006736261a04197076bf00abeee6a831983ef8302441add4ef06b0da1b672bf6d9380e9553ff0985441795d437cdb5b685aba840453f8f46b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00d4761c4f0012a10b2c9b38c087f032e94d241f8b182edf5610c9d336e2d114", - "blobPublicInputs": "0x01cb2643c794ffd2835b698dffc25f63cfff60717970cd3e7f7c0fb91f8303b80e8146e9a02fbb7bd2ff2df8550f8f2bf1c36eda19989d2153fd161a3bf214b35de7f666c8edd3cf3471753892f8f732973d009e684843388c18516476687d91b4f3cb75876a86c8edde736e313975c9cf1486d38d2c4ff8dad0667a878b196d41db63ab7d6d1893f0f432f6ea73c736b6393353efca34a3dcdc7db71ae0fd0a4443ef02bf48f1bf68b38a370de4886ec6a846a3ba62ff186072d2b25992bcd1", + "header": "0x2a05cb8aeefe9b9797f90650eae072f5ab7437807e62f9724ce190046777986000000001000000000000000000000000000000000000000000000000000000000000000400476e8bde67f5103417638177f69bafaab0a230f87b856043fe8fc0c8643f5f00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c000ca4a4610ad22c97c9161cedcf01faa3619f1b85457f1627d09627b71903a62e33ee2008411c04b99c24b313513d097a0d21a5040b6193d1f978b8226892d60000001000553ea03210e12bf95ed15f0105108f39db784d318cfe9b52cba413618711ce000001001d52eeaaacb445d9193d29e0df8f0ad4bf69bc457fe955b8e05b48ae3fdc3b3f00000180160cf8d0dbcc7b6a69aede9d89adb66554ba8054d9944b6ab5475e155e8f73d4000001800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000006738c8cacf4026defdbcf6d380561d2efbd56b77bb010b881d8e356ffb1a70658c67ac17b27be96faeab7707331b882e25a7a79c087ddcd1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x004b9ba8cfe9fd12d85ee92cf79a2f5d66f41d7cf4b4c8a637b18362695deb5d", + "blobInputs": "0x0101cb2643c794ffd2835b698dffc25f63cfff60717970cd3e7f7c0fb91f8303b80e8146e9a02fbb7bd2ff2df8550f8f2bf1c36eda19989d2153fd161a3bf214b35de7f666c8edd3cf3471753892f8f732973d009e684843388c18516476687d91b4f3cb75876a86c8edde736e313975c9cf1486d38d2c4ff8dad0667a878b196d41db63ab7d6d1893f0f432f6ea73c736b6393353efca34a3dcdc7db71ae0fd0a4443ef02bf48f1bf68b38a370de4886ec6a846a3ba62ff186072d2b25992bcd1", "numTxs": 4 } } \ No newline at end of file diff --git a/l1-contracts/test/fixtures/mixed_block_2.json b/l1-contracts/test/fixtures/mixed_block_2.json index 48f4f2b9492..e552dc84d2f 100644 --- a/l1-contracts/test/fixtures/mixed_block_2.json +++ b/l1-contracts/test/fixtures/mixed_block_2.json @@ -90,12 +90,12 @@ ] }, "block": { - "archive": "0x0363a4e20e16883d07b4294487e50ea28ed1f2f654ecfa3a0f207752e895b36d", - "blockHash": "0x2e34a3547970824b72dbf61499bf29472de88fcf22540ff1d74001922cd810d6", + "archive": "0x06cf8079750b0354c4660de3a4d8a0e5a044296e0de790b3207e9808e6f1a296", + "blockHash": "0x25937a40e15f769534580a01c21aa2109c13468cb65a9814e535f505b97b9886", "body": "0x00000008000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000041000000000000000000000000000000000000000000000000000000000000004100100000000000000000000000000000000000000000000000000000000000410020000000000000000000000000000000000000000000000000000000000041003000000000000000000000000000000000000000000000000000000000004100400000000000000000000000000000000000000000000000000000000000410050000000000000000000000000000000000000000000000000000000000041006000000000000000000000000000000000000000000000000000000000004100700000000000000000000000000000000000000000000000000000000000410080000000000000000000000000000000000000000000000000000000000041009000000000000000000000000000000000000000000000000000000000004100a000000000000000000000000000000000000000000000000000000000004100b000000000000000000000000000000000000000000000000000000000004100c000000000000000000000000000000000000000000000000000000000004100d000000000000000000000000000000000000000000000000000000000004100e000000000000000000000000000000000000000000000000000000000004100f0000000000000000000000000000000000000000000000000000000000041010000000000000000000000000000000000000000000000000000000000004101100000000000000000000000000000000000000000000000000000000000410120000000000000000000000000000000000000000000000000000000000041013000000000000000000000000000000000000000000000000000000000004101400000000000000000000000000000000000000000000000000000000000410150000000000000000000000000000000000000000000000000000000000041016000000000000000000000000000000000000000000000000000000000004101700000000000000000000000000000000000000000000000000000000000410180000000000000000000000000000000000000000000000000000000000041019000000000000000000000000000000000000000000000000000000000004101a000000000000000000000000000000000000000000000000000000000004101b000000000000000000000000000000000000000000000000000000000004101c000000000000000000000000000000000000000000000000000000000004101d000000000000000000000000000000000000000000000000000000000004101e000000000000000000000000000000000000000000000000000000000004101f0000000000000000000000000000000000000000000000000000000000041020000000000000000000000000000000000000000000000000000000000004102100000000000000000000000000000000000000000000000000000000000410220000000000000000000000000000000000000000000000000000000000041023000000000000000000000000000000000000000000000000000000000004102400000000000000000000000000000000000000000000000000000000000410250000000000000000000000000000000000000000000000000000000000041026000000000000000000000000000000000000000000000000000000000004102700000000000000000000000000000000000000000000000000000000000410280000000000000000000000000000000000000000000000000000000000041029000000000000000000000000000000000000000000000000000000000004102a000000000000000000000000000000000000000000000000000000000004102b000000000000000000000000000000000000000000000000000000000004102c000000000000000000000000000000000000000000000000000000000004102d000000000000000000000000000000000000000000000000000000000004102e000000000000000000000000000000000000000000000000000000000004102f0000000000000000000000000000000000000000000000000000000000041030000000000000000000000000000000000000000000000000000000000004103100000000000000000000000000000000000000000000000000000000000410320000000000000000000000000000000000000000000000000000000000041033000000000000000000000000000000000000000000000000000000000004103400000000000000000000000000000000000000000000000000000000000410350000000000000000000000000000000000000000000000000000000000041036000000000000000000000000000000000000000000000000000000000004103700000000000000000000000000000000000000000000000000000000000410380000000000000000000000000000000000000000000000000000000000041039000000000000000000000000000000000000000000000000000000000004103a000000000000000000000000000000000000000000000000000000000004103b000000000000000000000000000000000000000000000000000000000004103c000000000000000000000000000000000000000000000000000000000004103d000000000000000000000000000000000000000000000000000000000004103e000000000000000000000000000000000000000000000000000000000004103f3f0000000000000000000000000000000000000000000000000000000000041100000000000000000000000000000000000000000000000000000000000004110100000000000000000000000000000000000000000000000000000000000411020000000000000000000000000000000000000000000000000000000000041103000000000000000000000000000000000000000000000000000000000004110400000000000000000000000000000000000000000000000000000000000411050000000000000000000000000000000000000000000000000000000000041106000000000000000000000000000000000000000000000000000000000004110700000000000000000000000000000000000000000000000000000000000411080000000000000000000000000000000000000000000000000000000000041109000000000000000000000000000000000000000000000000000000000004110a000000000000000000000000000000000000000000000000000000000004110b000000000000000000000000000000000000000000000000000000000004110c000000000000000000000000000000000000000000000000000000000004110d000000000000000000000000000000000000000000000000000000000004110e000000000000000000000000000000000000000000000000000000000004110f0000000000000000000000000000000000000000000000000000000000041110000000000000000000000000000000000000000000000000000000000004111100000000000000000000000000000000000000000000000000000000000411120000000000000000000000000000000000000000000000000000000000041113000000000000000000000000000000000000000000000000000000000004111400000000000000000000000000000000000000000000000000000000000411150000000000000000000000000000000000000000000000000000000000041116000000000000000000000000000000000000000000000000000000000004111700000000000000000000000000000000000000000000000000000000000411180000000000000000000000000000000000000000000000000000000000041119000000000000000000000000000000000000000000000000000000000004111a000000000000000000000000000000000000000000000000000000000004111b000000000000000000000000000000000000000000000000000000000004111c000000000000000000000000000000000000000000000000000000000004111d000000000000000000000000000000000000000000000000000000000004111e000000000000000000000000000000000000000000000000000000000004111f0000000000000000000000000000000000000000000000000000000000041120000000000000000000000000000000000000000000000000000000000004112100000000000000000000000000000000000000000000000000000000000411220000000000000000000000000000000000000000000000000000000000041123000000000000000000000000000000000000000000000000000000000004112400000000000000000000000000000000000000000000000000000000000411250000000000000000000000000000000000000000000000000000000000041126000000000000000000000000000000000000000000000000000000000004112700000000000000000000000000000000000000000000000000000000000411280000000000000000000000000000000000000000000000000000000000041129000000000000000000000000000000000000000000000000000000000004112a000000000000000000000000000000000000000000000000000000000004112b000000000000000000000000000000000000000000000000000000000004112c000000000000000000000000000000000000000000000000000000000004112d000000000000000000000000000000000000000000000000000000000004112e000000000000000000000000000000000000000000000000000000000004112f0000000000000000000000000000000000000000000000000000000000041130000000000000000000000000000000000000000000000000000000000004113100000000000000000000000000000000000000000000000000000000000411320000000000000000000000000000000000000000000000000000000000041133000000000000000000000000000000000000000000000000000000000004113400000000000000000000000000000000000000000000000000000000000411350000000000000000000000000000000000000000000000000000000000041136000000000000000000000000000000000000000000000000000000000004113700000000000000000000000000000000000000000000000000000000000411380000000000000000000000000000000000000000000000000000000000041139000000000000000000000000000000000000000000000000000000000004113a000000000000000000000000000000000000000000000000000000000004113b000000000000000000000000000000000000000000000000000000000004113c000000000000000000000000000000000000000000000000000000000004113d000000000000000000000000000000000000000000000000000000000004113e080097a6ec570e9b8e257647c9c74c5ad3edc57ca5ef6ae44d80b3c30d1d99b9b300ce48ec41d1edde0066fab553a456ae2f380d14fa8f956af1fb0217513a598900619ff12eaf97f63aa2a2311de3b6571a7b880a5247cb33b6a74787bf3f9bd5007854a2fad4e1801c6404394bf3d37ab08c135ea38a1974242e39a21273685f000f55796e72957a819e68a22e8602d73c3ba3718a5a4bd92b80b0aa444b182a00788b6e9874fb040ee679a7fae257190099a605229b948334e54a57739535d4004f1658ee3c1a91627e5d72f5a731f0796299df82ab41e72c88eee0c82fa85e003ee802add96628c693ed71afa9908138ba5a6fbf0a5f29a9c74e4e42aba6713f0000000000000000000000000000000000000000000000000000000000042000000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042001000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042002000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042003000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042004000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042005000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420060000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004200700000000000000000000000000000000000000000000000000000000000420110000000000000000000000000000000000000000000000000000000000042008000000000000000000000000000000000000000000000000000000000004201200000000000000000000000000000000000000000000000000000000000420090000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004200a0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004200b0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004200c0000000000000000000000000000000000000000000000000000000000042016000000000000000000000000000000000000000000000000000000000004200d0000000000000000000000000000000000000000000000000000000000042017000000000000000000000000000000000000000000000000000000000004200e0000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004200f00000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042010000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042011000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042012000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042013000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042014000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042015000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420160000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004201700000000000000000000000000000000000000000000000000000000000420210000000000000000000000000000000000000000000000000000000000042018000000000000000000000000000000000000000000000000000000000004202200000000000000000000000000000000000000000000000000000000000420190000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004201a0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004201b0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004201c0000000000000000000000000000000000000000000000000000000000042026000000000000000000000000000000000000000000000000000000000004201d0000000000000000000000000000000000000000000000000000000000042027000000000000000000000000000000000000000000000000000000000004201e0000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004201f00000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042020000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042021000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042022000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042023000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042024000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042025000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420260000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004202700000000000000000000000000000000000000000000000000000000000420310000000000000000000000000000000000000000000000000000000000042028000000000000000000000000000000000000000000000000000000000004203200000000000000000000000000000000000000000000000000000000000420290000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004202a0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004202b0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004202c0000000000000000000000000000000000000000000000000000000000042036000000000000000000000000000000000000000000000000000000000004202d0000000000000000000000000000000000000000000000000000000000042037000000000000000000000000000000000000000000000000000000000004202e0000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004202f00000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042030000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042031000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042032000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042033000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042034000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042035000000000000000000000000000000000000000000000000000000000004203f00000000000000000000000000000000000000000000000000000000000420360000000000000000000000000000000000000000000000000000000000042040000000000000000000000000000000000000000000000000000000000004203700000000000000000000000000000000000000000000000000000000000420410000000000000000000000000000000000000000000000000000000000042038000000000000000000000000000000000000000000000000000000000004204200000000000000000000000000000000000000000000000000000000000420390000000000000000000000000000000000000000000000000000000000042043000000000000000000000000000000000000000000000000000000000004203a0000000000000000000000000000000000000000000000000000000000042044000000000000000000000000000000000000000000000000000000000004203b0000000000000000000000000000000000000000000000000000000000042045000000000000000000000000000000000000000000000000000000000004203c0000000000000000000000000000000000000000000000000000000000042046000000000000000000000000000000000000000000000000000000000004203d0000000000000000000000000000000000000000000000000000000000042047000000000000000000000000000000000000000000000000000000000004203e0000000000000000000000000000000000000000000000000000000000042048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000081000000000000000000000000000000000000000000000000000000000000008100100000000000000000000000000000000000000000000000000000000000810020000000000000000000000000000000000000000000000000000000000081003000000000000000000000000000000000000000000000000000000000008100400000000000000000000000000000000000000000000000000000000000810050000000000000000000000000000000000000000000000000000000000081006000000000000000000000000000000000000000000000000000000000008100700000000000000000000000000000000000000000000000000000000000810080000000000000000000000000000000000000000000000000000000000081009000000000000000000000000000000000000000000000000000000000008100a000000000000000000000000000000000000000000000000000000000008100b000000000000000000000000000000000000000000000000000000000008100c000000000000000000000000000000000000000000000000000000000008100d000000000000000000000000000000000000000000000000000000000008100e000000000000000000000000000000000000000000000000000000000008100f0000000000000000000000000000000000000000000000000000000000081010000000000000000000000000000000000000000000000000000000000008101100000000000000000000000000000000000000000000000000000000000810120000000000000000000000000000000000000000000000000000000000081013000000000000000000000000000000000000000000000000000000000008101400000000000000000000000000000000000000000000000000000000000810150000000000000000000000000000000000000000000000000000000000081016000000000000000000000000000000000000000000000000000000000008101700000000000000000000000000000000000000000000000000000000000810180000000000000000000000000000000000000000000000000000000000081019000000000000000000000000000000000000000000000000000000000008101a000000000000000000000000000000000000000000000000000000000008101b000000000000000000000000000000000000000000000000000000000008101c000000000000000000000000000000000000000000000000000000000008101d000000000000000000000000000000000000000000000000000000000008101e000000000000000000000000000000000000000000000000000000000008101f0000000000000000000000000000000000000000000000000000000000081020000000000000000000000000000000000000000000000000000000000008102100000000000000000000000000000000000000000000000000000000000810220000000000000000000000000000000000000000000000000000000000081023000000000000000000000000000000000000000000000000000000000008102400000000000000000000000000000000000000000000000000000000000810250000000000000000000000000000000000000000000000000000000000081026000000000000000000000000000000000000000000000000000000000008102700000000000000000000000000000000000000000000000000000000000810280000000000000000000000000000000000000000000000000000000000081029000000000000000000000000000000000000000000000000000000000008102a000000000000000000000000000000000000000000000000000000000008102b000000000000000000000000000000000000000000000000000000000008102c000000000000000000000000000000000000000000000000000000000008102d000000000000000000000000000000000000000000000000000000000008102e000000000000000000000000000000000000000000000000000000000008102f0000000000000000000000000000000000000000000000000000000000081030000000000000000000000000000000000000000000000000000000000008103100000000000000000000000000000000000000000000000000000000000810320000000000000000000000000000000000000000000000000000000000081033000000000000000000000000000000000000000000000000000000000008103400000000000000000000000000000000000000000000000000000000000810350000000000000000000000000000000000000000000000000000000000081036000000000000000000000000000000000000000000000000000000000008103700000000000000000000000000000000000000000000000000000000000810380000000000000000000000000000000000000000000000000000000000081039000000000000000000000000000000000000000000000000000000000008103a000000000000000000000000000000000000000000000000000000000008103b000000000000000000000000000000000000000000000000000000000008103c000000000000000000000000000000000000000000000000000000000008103d000000000000000000000000000000000000000000000000000000000008103e000000000000000000000000000000000000000000000000000000000008103f3f0000000000000000000000000000000000000000000000000000000000081100000000000000000000000000000000000000000000000000000000000008110100000000000000000000000000000000000000000000000000000000000811020000000000000000000000000000000000000000000000000000000000081103000000000000000000000000000000000000000000000000000000000008110400000000000000000000000000000000000000000000000000000000000811050000000000000000000000000000000000000000000000000000000000081106000000000000000000000000000000000000000000000000000000000008110700000000000000000000000000000000000000000000000000000000000811080000000000000000000000000000000000000000000000000000000000081109000000000000000000000000000000000000000000000000000000000008110a000000000000000000000000000000000000000000000000000000000008110b000000000000000000000000000000000000000000000000000000000008110c000000000000000000000000000000000000000000000000000000000008110d000000000000000000000000000000000000000000000000000000000008110e000000000000000000000000000000000000000000000000000000000008110f0000000000000000000000000000000000000000000000000000000000081110000000000000000000000000000000000000000000000000000000000008111100000000000000000000000000000000000000000000000000000000000811120000000000000000000000000000000000000000000000000000000000081113000000000000000000000000000000000000000000000000000000000008111400000000000000000000000000000000000000000000000000000000000811150000000000000000000000000000000000000000000000000000000000081116000000000000000000000000000000000000000000000000000000000008111700000000000000000000000000000000000000000000000000000000000811180000000000000000000000000000000000000000000000000000000000081119000000000000000000000000000000000000000000000000000000000008111a000000000000000000000000000000000000000000000000000000000008111b000000000000000000000000000000000000000000000000000000000008111c000000000000000000000000000000000000000000000000000000000008111d000000000000000000000000000000000000000000000000000000000008111e000000000000000000000000000000000000000000000000000000000008111f0000000000000000000000000000000000000000000000000000000000081120000000000000000000000000000000000000000000000000000000000008112100000000000000000000000000000000000000000000000000000000000811220000000000000000000000000000000000000000000000000000000000081123000000000000000000000000000000000000000000000000000000000008112400000000000000000000000000000000000000000000000000000000000811250000000000000000000000000000000000000000000000000000000000081126000000000000000000000000000000000000000000000000000000000008112700000000000000000000000000000000000000000000000000000000000811280000000000000000000000000000000000000000000000000000000000081129000000000000000000000000000000000000000000000000000000000008112a000000000000000000000000000000000000000000000000000000000008112b000000000000000000000000000000000000000000000000000000000008112c000000000000000000000000000000000000000000000000000000000008112d000000000000000000000000000000000000000000000000000000000008112e000000000000000000000000000000000000000000000000000000000008112f0000000000000000000000000000000000000000000000000000000000081130000000000000000000000000000000000000000000000000000000000008113100000000000000000000000000000000000000000000000000000000000811320000000000000000000000000000000000000000000000000000000000081133000000000000000000000000000000000000000000000000000000000008113400000000000000000000000000000000000000000000000000000000000811350000000000000000000000000000000000000000000000000000000000081136000000000000000000000000000000000000000000000000000000000008113700000000000000000000000000000000000000000000000000000000000811380000000000000000000000000000000000000000000000000000000000081139000000000000000000000000000000000000000000000000000000000008113a000000000000000000000000000000000000000000000000000000000008113b000000000000000000000000000000000000000000000000000000000008113c000000000000000000000000000000000000000000000000000000000008113d000000000000000000000000000000000000000000000000000000000008113e08003c0472260790b0bdfb8ae4dc4d437e7686b73643f2198970d84e1059a5f13500bfd46275a318e438726ff2765ae154b63ab8a0daebcbed668a5f58a0e63dc1007906b9418dc758c6b4f8454c69baa48b7889b6b511d707abe8e2cb8f7c397300aeb60c4d65a44f122e58bf9565dfe2024b3ae654d5cf2e47ecb035d53c927000bf82e8cda20345f37bbb1de3932172324b57f0b98be483392697b168e3bba8000fb4bbad884ef30edf68e45a6cf2733fcf50310c69d7c1432b29af2c0aa8040023e1622d27fee3b4a40ab975ae0eb2e31619ef3dc76eb858f7fddb6a056131004689cd7007daf98dd3218b839b8e6a29f957154347b391fdb376bd0b344be23f0000000000000000000000000000000000000000000000000000000000082000000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082001000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082002000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082003000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082004000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082005000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820060000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008200700000000000000000000000000000000000000000000000000000000000820110000000000000000000000000000000000000000000000000000000000082008000000000000000000000000000000000000000000000000000000000008201200000000000000000000000000000000000000000000000000000000000820090000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008200a0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008200b0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008200c0000000000000000000000000000000000000000000000000000000000082016000000000000000000000000000000000000000000000000000000000008200d0000000000000000000000000000000000000000000000000000000000082017000000000000000000000000000000000000000000000000000000000008200e0000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008200f00000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082010000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082011000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082012000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082013000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082014000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082015000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820160000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008201700000000000000000000000000000000000000000000000000000000000820210000000000000000000000000000000000000000000000000000000000082018000000000000000000000000000000000000000000000000000000000008202200000000000000000000000000000000000000000000000000000000000820190000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008201a0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008201b0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008201c0000000000000000000000000000000000000000000000000000000000082026000000000000000000000000000000000000000000000000000000000008201d0000000000000000000000000000000000000000000000000000000000082027000000000000000000000000000000000000000000000000000000000008201e0000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008201f00000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082020000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082021000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082022000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082023000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082024000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082025000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820260000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008202700000000000000000000000000000000000000000000000000000000000820310000000000000000000000000000000000000000000000000000000000082028000000000000000000000000000000000000000000000000000000000008203200000000000000000000000000000000000000000000000000000000000820290000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008202a0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008202b0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008202c0000000000000000000000000000000000000000000000000000000000082036000000000000000000000000000000000000000000000000000000000008202d0000000000000000000000000000000000000000000000000000000000082037000000000000000000000000000000000000000000000000000000000008202e0000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008202f00000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082030000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082031000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082032000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082033000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082034000000000000000000000000000000000000000000000000000000000008203e0000000000000000000000000000000000000000000000000000000000082035000000000000000000000000000000000000000000000000000000000008203f00000000000000000000000000000000000000000000000000000000000820360000000000000000000000000000000000000000000000000000000000082040000000000000000000000000000000000000000000000000000000000008203700000000000000000000000000000000000000000000000000000000000820410000000000000000000000000000000000000000000000000000000000082038000000000000000000000000000000000000000000000000000000000008204200000000000000000000000000000000000000000000000000000000000820390000000000000000000000000000000000000000000000000000000000082043000000000000000000000000000000000000000000000000000000000008203a0000000000000000000000000000000000000000000000000000000000082044000000000000000000000000000000000000000000000000000000000008203b0000000000000000000000000000000000000000000000000000000000082045000000000000000000000000000000000000000000000000000000000008203c0000000000000000000000000000000000000000000000000000000000082046000000000000000000000000000000000000000000000000000000000008203d0000000000000000000000000000000000000000000000000000000000082047000000000000000000000000000000000000000000000000000000000008203e00000000000000000000000000000000000000000000000000000000000820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000c100000000000000000000000000000000000000000000000000000000000000c100100000000000000000000000000000000000000000000000000000000000c100200000000000000000000000000000000000000000000000000000000000c100300000000000000000000000000000000000000000000000000000000000c100400000000000000000000000000000000000000000000000000000000000c100500000000000000000000000000000000000000000000000000000000000c100600000000000000000000000000000000000000000000000000000000000c100700000000000000000000000000000000000000000000000000000000000c100800000000000000000000000000000000000000000000000000000000000c100900000000000000000000000000000000000000000000000000000000000c100a00000000000000000000000000000000000000000000000000000000000c100b00000000000000000000000000000000000000000000000000000000000c100c00000000000000000000000000000000000000000000000000000000000c100d00000000000000000000000000000000000000000000000000000000000c100e00000000000000000000000000000000000000000000000000000000000c100f00000000000000000000000000000000000000000000000000000000000c101000000000000000000000000000000000000000000000000000000000000c101100000000000000000000000000000000000000000000000000000000000c101200000000000000000000000000000000000000000000000000000000000c101300000000000000000000000000000000000000000000000000000000000c101400000000000000000000000000000000000000000000000000000000000c101500000000000000000000000000000000000000000000000000000000000c101600000000000000000000000000000000000000000000000000000000000c101700000000000000000000000000000000000000000000000000000000000c101800000000000000000000000000000000000000000000000000000000000c101900000000000000000000000000000000000000000000000000000000000c101a00000000000000000000000000000000000000000000000000000000000c101b00000000000000000000000000000000000000000000000000000000000c101c00000000000000000000000000000000000000000000000000000000000c101d00000000000000000000000000000000000000000000000000000000000c101e00000000000000000000000000000000000000000000000000000000000c101f00000000000000000000000000000000000000000000000000000000000c102000000000000000000000000000000000000000000000000000000000000c102100000000000000000000000000000000000000000000000000000000000c102200000000000000000000000000000000000000000000000000000000000c102300000000000000000000000000000000000000000000000000000000000c102400000000000000000000000000000000000000000000000000000000000c102500000000000000000000000000000000000000000000000000000000000c102600000000000000000000000000000000000000000000000000000000000c102700000000000000000000000000000000000000000000000000000000000c102800000000000000000000000000000000000000000000000000000000000c102900000000000000000000000000000000000000000000000000000000000c102a00000000000000000000000000000000000000000000000000000000000c102b00000000000000000000000000000000000000000000000000000000000c102c00000000000000000000000000000000000000000000000000000000000c102d00000000000000000000000000000000000000000000000000000000000c102e00000000000000000000000000000000000000000000000000000000000c102f00000000000000000000000000000000000000000000000000000000000c103000000000000000000000000000000000000000000000000000000000000c103100000000000000000000000000000000000000000000000000000000000c103200000000000000000000000000000000000000000000000000000000000c103300000000000000000000000000000000000000000000000000000000000c103400000000000000000000000000000000000000000000000000000000000c103500000000000000000000000000000000000000000000000000000000000c103600000000000000000000000000000000000000000000000000000000000c103700000000000000000000000000000000000000000000000000000000000c103800000000000000000000000000000000000000000000000000000000000c103900000000000000000000000000000000000000000000000000000000000c103a00000000000000000000000000000000000000000000000000000000000c103b00000000000000000000000000000000000000000000000000000000000c103c00000000000000000000000000000000000000000000000000000000000c103d00000000000000000000000000000000000000000000000000000000000c103e00000000000000000000000000000000000000000000000000000000000c103f3f00000000000000000000000000000000000000000000000000000000000c110000000000000000000000000000000000000000000000000000000000000c110100000000000000000000000000000000000000000000000000000000000c110200000000000000000000000000000000000000000000000000000000000c110300000000000000000000000000000000000000000000000000000000000c110400000000000000000000000000000000000000000000000000000000000c110500000000000000000000000000000000000000000000000000000000000c110600000000000000000000000000000000000000000000000000000000000c110700000000000000000000000000000000000000000000000000000000000c110800000000000000000000000000000000000000000000000000000000000c110900000000000000000000000000000000000000000000000000000000000c110a00000000000000000000000000000000000000000000000000000000000c110b00000000000000000000000000000000000000000000000000000000000c110c00000000000000000000000000000000000000000000000000000000000c110d00000000000000000000000000000000000000000000000000000000000c110e00000000000000000000000000000000000000000000000000000000000c110f00000000000000000000000000000000000000000000000000000000000c111000000000000000000000000000000000000000000000000000000000000c111100000000000000000000000000000000000000000000000000000000000c111200000000000000000000000000000000000000000000000000000000000c111300000000000000000000000000000000000000000000000000000000000c111400000000000000000000000000000000000000000000000000000000000c111500000000000000000000000000000000000000000000000000000000000c111600000000000000000000000000000000000000000000000000000000000c111700000000000000000000000000000000000000000000000000000000000c111800000000000000000000000000000000000000000000000000000000000c111900000000000000000000000000000000000000000000000000000000000c111a00000000000000000000000000000000000000000000000000000000000c111b00000000000000000000000000000000000000000000000000000000000c111c00000000000000000000000000000000000000000000000000000000000c111d00000000000000000000000000000000000000000000000000000000000c111e00000000000000000000000000000000000000000000000000000000000c111f00000000000000000000000000000000000000000000000000000000000c112000000000000000000000000000000000000000000000000000000000000c112100000000000000000000000000000000000000000000000000000000000c112200000000000000000000000000000000000000000000000000000000000c112300000000000000000000000000000000000000000000000000000000000c112400000000000000000000000000000000000000000000000000000000000c112500000000000000000000000000000000000000000000000000000000000c112600000000000000000000000000000000000000000000000000000000000c112700000000000000000000000000000000000000000000000000000000000c112800000000000000000000000000000000000000000000000000000000000c112900000000000000000000000000000000000000000000000000000000000c112a00000000000000000000000000000000000000000000000000000000000c112b00000000000000000000000000000000000000000000000000000000000c112c00000000000000000000000000000000000000000000000000000000000c112d00000000000000000000000000000000000000000000000000000000000c112e00000000000000000000000000000000000000000000000000000000000c112f00000000000000000000000000000000000000000000000000000000000c113000000000000000000000000000000000000000000000000000000000000c113100000000000000000000000000000000000000000000000000000000000c113200000000000000000000000000000000000000000000000000000000000c113300000000000000000000000000000000000000000000000000000000000c113400000000000000000000000000000000000000000000000000000000000c113500000000000000000000000000000000000000000000000000000000000c113600000000000000000000000000000000000000000000000000000000000c113700000000000000000000000000000000000000000000000000000000000c113800000000000000000000000000000000000000000000000000000000000c113900000000000000000000000000000000000000000000000000000000000c113a00000000000000000000000000000000000000000000000000000000000c113b00000000000000000000000000000000000000000000000000000000000c113c00000000000000000000000000000000000000000000000000000000000c113d00000000000000000000000000000000000000000000000000000000000c113e0800f8029be42ec3f25204907ca981fb71e5b357093eb5db10fc01ca98a4e4154c0030e13d351a5bf1d5a040e82a163ca57017f39162693f85c571e441e36d702d00a550ae0f39f977d9473d6de1be3232fc68ed0c4a601d53542148695102cfc9005580bc65e4bff9c8fffa64db02c0fa6af14d9d26fd962f4c5904cbd3ddec2500758c4a0d43dfec788b2f580877c4f473adec8f168ea24424f2600e4eb4916f00342602bf90d10f8ca8e582a894dcc4c02bb89fe458532e0c632b53bae54b4d00ca43ab78ab834337e9964d84a0674c9adabdca140539c5a6bc96e0ba9a51f6004ffbfd91be292a7c6a0e255e50caa156ac2d628b40ad2128c4ab63a92d8a1c3f00000000000000000000000000000000000000000000000000000000000c200000000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c200100000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c200200000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c200300000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c200400000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c200500000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c200600000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c200700000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c200800000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c200900000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c200a00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c200b00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c200c00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c200d00000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c200e00000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c200f00000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c201000000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c201100000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c201200000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c201300000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c201400000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c201500000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c201600000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c201700000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c201800000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c201900000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c201a00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c201b00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c201c00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c201d00000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c201e00000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c201f00000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c202000000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c202100000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c202200000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c202300000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c202400000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c202500000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c202600000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c202700000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c202800000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c202900000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c202a00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c202b00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c202c00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c202d00000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c202e00000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c202f00000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c203000000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c203100000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c203200000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c203300000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c203400000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c203500000000000000000000000000000000000000000000000000000000000c203f00000000000000000000000000000000000000000000000000000000000c203600000000000000000000000000000000000000000000000000000000000c204000000000000000000000000000000000000000000000000000000000000c203700000000000000000000000000000000000000000000000000000000000c204100000000000000000000000000000000000000000000000000000000000c203800000000000000000000000000000000000000000000000000000000000c204200000000000000000000000000000000000000000000000000000000000c203900000000000000000000000000000000000000000000000000000000000c204300000000000000000000000000000000000000000000000000000000000c203a00000000000000000000000000000000000000000000000000000000000c204400000000000000000000000000000000000000000000000000000000000c203b00000000000000000000000000000000000000000000000000000000000c204500000000000000000000000000000000000000000000000000000000000c203c00000000000000000000000000000000000000000000000000000000000c204600000000000000000000000000000000000000000000000000000000000c203d00000000000000000000000000000000000000000000000000000000000c204700000000000000000000000000000000000000000000000000000000000c203e00000000000000000000000000000000000000000000000000000000000c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000000000000010100100000000000000000000000000000000000000000000000000000000001010020000000000000000000000000000000000000000000000000000000000101003000000000000000000000000000000000000000000000000000000000010100400000000000000000000000000000000000000000000000000000000001010050000000000000000000000000000000000000000000000000000000000101006000000000000000000000000000000000000000000000000000000000010100700000000000000000000000000000000000000000000000000000000001010080000000000000000000000000000000000000000000000000000000000101009000000000000000000000000000000000000000000000000000000000010100a000000000000000000000000000000000000000000000000000000000010100b000000000000000000000000000000000000000000000000000000000010100c000000000000000000000000000000000000000000000000000000000010100d000000000000000000000000000000000000000000000000000000000010100e000000000000000000000000000000000000000000000000000000000010100f0000000000000000000000000000000000000000000000000000000000101010000000000000000000000000000000000000000000000000000000000010101100000000000000000000000000000000000000000000000000000000001010120000000000000000000000000000000000000000000000000000000000101013000000000000000000000000000000000000000000000000000000000010101400000000000000000000000000000000000000000000000000000000001010150000000000000000000000000000000000000000000000000000000000101016000000000000000000000000000000000000000000000000000000000010101700000000000000000000000000000000000000000000000000000000001010180000000000000000000000000000000000000000000000000000000000101019000000000000000000000000000000000000000000000000000000000010101a000000000000000000000000000000000000000000000000000000000010101b000000000000000000000000000000000000000000000000000000000010101c000000000000000000000000000000000000000000000000000000000010101d000000000000000000000000000000000000000000000000000000000010101e000000000000000000000000000000000000000000000000000000000010101f0000000000000000000000000000000000000000000000000000000000101020000000000000000000000000000000000000000000000000000000000010102100000000000000000000000000000000000000000000000000000000001010220000000000000000000000000000000000000000000000000000000000101023000000000000000000000000000000000000000000000000000000000010102400000000000000000000000000000000000000000000000000000000001010250000000000000000000000000000000000000000000000000000000000101026000000000000000000000000000000000000000000000000000000000010102700000000000000000000000000000000000000000000000000000000001010280000000000000000000000000000000000000000000000000000000000101029000000000000000000000000000000000000000000000000000000000010102a000000000000000000000000000000000000000000000000000000000010102b000000000000000000000000000000000000000000000000000000000010102c000000000000000000000000000000000000000000000000000000000010102d000000000000000000000000000000000000000000000000000000000010102e000000000000000000000000000000000000000000000000000000000010102f0000000000000000000000000000000000000000000000000000000000101030000000000000000000000000000000000000000000000000000000000010103100000000000000000000000000000000000000000000000000000000001010320000000000000000000000000000000000000000000000000000000000101033000000000000000000000000000000000000000000000000000000000010103400000000000000000000000000000000000000000000000000000000001010350000000000000000000000000000000000000000000000000000000000101036000000000000000000000000000000000000000000000000000000000010103700000000000000000000000000000000000000000000000000000000001010380000000000000000000000000000000000000000000000000000000000101039000000000000000000000000000000000000000000000000000000000010103a000000000000000000000000000000000000000000000000000000000010103b000000000000000000000000000000000000000000000000000000000010103c000000000000000000000000000000000000000000000000000000000010103d000000000000000000000000000000000000000000000000000000000010103e000000000000000000000000000000000000000000000000000000000010103f3f0000000000000000000000000000000000000000000000000000000000101100000000000000000000000000000000000000000000000000000000000010110100000000000000000000000000000000000000000000000000000000001011020000000000000000000000000000000000000000000000000000000000101103000000000000000000000000000000000000000000000000000000000010110400000000000000000000000000000000000000000000000000000000001011050000000000000000000000000000000000000000000000000000000000101106000000000000000000000000000000000000000000000000000000000010110700000000000000000000000000000000000000000000000000000000001011080000000000000000000000000000000000000000000000000000000000101109000000000000000000000000000000000000000000000000000000000010110a000000000000000000000000000000000000000000000000000000000010110b000000000000000000000000000000000000000000000000000000000010110c000000000000000000000000000000000000000000000000000000000010110d000000000000000000000000000000000000000000000000000000000010110e000000000000000000000000000000000000000000000000000000000010110f0000000000000000000000000000000000000000000000000000000000101110000000000000000000000000000000000000000000000000000000000010111100000000000000000000000000000000000000000000000000000000001011120000000000000000000000000000000000000000000000000000000000101113000000000000000000000000000000000000000000000000000000000010111400000000000000000000000000000000000000000000000000000000001011150000000000000000000000000000000000000000000000000000000000101116000000000000000000000000000000000000000000000000000000000010111700000000000000000000000000000000000000000000000000000000001011180000000000000000000000000000000000000000000000000000000000101119000000000000000000000000000000000000000000000000000000000010111a000000000000000000000000000000000000000000000000000000000010111b000000000000000000000000000000000000000000000000000000000010111c000000000000000000000000000000000000000000000000000000000010111d000000000000000000000000000000000000000000000000000000000010111e000000000000000000000000000000000000000000000000000000000010111f0000000000000000000000000000000000000000000000000000000000101120000000000000000000000000000000000000000000000000000000000010112100000000000000000000000000000000000000000000000000000000001011220000000000000000000000000000000000000000000000000000000000101123000000000000000000000000000000000000000000000000000000000010112400000000000000000000000000000000000000000000000000000000001011250000000000000000000000000000000000000000000000000000000000101126000000000000000000000000000000000000000000000000000000000010112700000000000000000000000000000000000000000000000000000000001011280000000000000000000000000000000000000000000000000000000000101129000000000000000000000000000000000000000000000000000000000010112a000000000000000000000000000000000000000000000000000000000010112b000000000000000000000000000000000000000000000000000000000010112c000000000000000000000000000000000000000000000000000000000010112d000000000000000000000000000000000000000000000000000000000010112e000000000000000000000000000000000000000000000000000000000010112f0000000000000000000000000000000000000000000000000000000000101130000000000000000000000000000000000000000000000000000000000010113100000000000000000000000000000000000000000000000000000000001011320000000000000000000000000000000000000000000000000000000000101133000000000000000000000000000000000000000000000000000000000010113400000000000000000000000000000000000000000000000000000000001011350000000000000000000000000000000000000000000000000000000000101136000000000000000000000000000000000000000000000000000000000010113700000000000000000000000000000000000000000000000000000000001011380000000000000000000000000000000000000000000000000000000000101139000000000000000000000000000000000000000000000000000000000010113a000000000000000000000000000000000000000000000000000000000010113b000000000000000000000000000000000000000000000000000000000010113c000000000000000000000000000000000000000000000000000000000010113d000000000000000000000000000000000000000000000000000000000010113e080099145b6c0d32753835121f8b271186d01236948a4622ce78a98347fcfc98390085277a27c6acbd5ffc4c19cd65fc30056999e9bec36998f753132db0ff8e2300f3cf77a7261759ebd5f4149f6ad56746f4499cfcd4adf27a1d373f77da64d5009bc6e0e994a23cde8c95b90c1acc1b4a480c6599d1df2c3f9f6e76f3d1aff200d7a1c4a2700dacaaf07f1f0ff33837bdbabcf0b9ace17efabe0761708c4bb900dbeb8e96d14f21e57d5786b6d6ae7e5ddb1bb35935c0fb246d4bdbca62e02c00fbf12b5e0df6223b801088798e4e04d2a92ffe9a11639b7f0ce314e3412a8000d796e0724de03b796ba77069fcd6cf921e566f3aed15eb3e77258add74e9ff3f0000000000000000000000000000000000000000000000000000000000102000000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102001000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102002000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102003000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102004000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102005000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020060000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010200700000000000000000000000000000000000000000000000000000000001020110000000000000000000000000000000000000000000000000000000000102008000000000000000000000000000000000000000000000000000000000010201200000000000000000000000000000000000000000000000000000000001020090000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010200a0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010200b0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010200c0000000000000000000000000000000000000000000000000000000000102016000000000000000000000000000000000000000000000000000000000010200d0000000000000000000000000000000000000000000000000000000000102017000000000000000000000000000000000000000000000000000000000010200e0000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010200f00000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102010000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102011000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102012000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102013000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102014000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102015000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020160000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010201700000000000000000000000000000000000000000000000000000000001020210000000000000000000000000000000000000000000000000000000000102018000000000000000000000000000000000000000000000000000000000010202200000000000000000000000000000000000000000000000000000000001020190000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010201a0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010201b0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010201c0000000000000000000000000000000000000000000000000000000000102026000000000000000000000000000000000000000000000000000000000010201d0000000000000000000000000000000000000000000000000000000000102027000000000000000000000000000000000000000000000000000000000010201e0000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010201f00000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102020000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102021000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102022000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102023000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102024000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102025000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020260000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010202700000000000000000000000000000000000000000000000000000000001020310000000000000000000000000000000000000000000000000000000000102028000000000000000000000000000000000000000000000000000000000010203200000000000000000000000000000000000000000000000000000000001020290000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010202a0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010202b0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010202c0000000000000000000000000000000000000000000000000000000000102036000000000000000000000000000000000000000000000000000000000010202d0000000000000000000000000000000000000000000000000000000000102037000000000000000000000000000000000000000000000000000000000010202e0000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010202f00000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102030000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102031000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102032000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102033000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102034000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102035000000000000000000000000000000000000000000000000000000000010203f00000000000000000000000000000000000000000000000000000000001020360000000000000000000000000000000000000000000000000000000000102040000000000000000000000000000000000000000000000000000000000010203700000000000000000000000000000000000000000000000000000000001020410000000000000000000000000000000000000000000000000000000000102038000000000000000000000000000000000000000000000000000000000010204200000000000000000000000000000000000000000000000000000000001020390000000000000000000000000000000000000000000000000000000000102043000000000000000000000000000000000000000000000000000000000010203a0000000000000000000000000000000000000000000000000000000000102044000000000000000000000000000000000000000000000000000000000010203b0000000000000000000000000000000000000000000000000000000000102045000000000000000000000000000000000000000000000000000000000010203c0000000000000000000000000000000000000000000000000000000000102046000000000000000000000000000000000000000000000000000000000010203d0000000000000000000000000000000000000000000000000000000000102047000000000000000000000000000000000000000000000000000000000010203e0000000000000000000000000000000000000000000000000000000000102048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000141000000000000000000000000000000000000000000000000000000000000014100100000000000000000000000000000000000000000000000000000000001410020000000000000000000000000000000000000000000000000000000000141003000000000000000000000000000000000000000000000000000000000014100400000000000000000000000000000000000000000000000000000000001410050000000000000000000000000000000000000000000000000000000000141006000000000000000000000000000000000000000000000000000000000014100700000000000000000000000000000000000000000000000000000000001410080000000000000000000000000000000000000000000000000000000000141009000000000000000000000000000000000000000000000000000000000014100a000000000000000000000000000000000000000000000000000000000014100b000000000000000000000000000000000000000000000000000000000014100c000000000000000000000000000000000000000000000000000000000014100d000000000000000000000000000000000000000000000000000000000014100e000000000000000000000000000000000000000000000000000000000014100f0000000000000000000000000000000000000000000000000000000000141010000000000000000000000000000000000000000000000000000000000014101100000000000000000000000000000000000000000000000000000000001410120000000000000000000000000000000000000000000000000000000000141013000000000000000000000000000000000000000000000000000000000014101400000000000000000000000000000000000000000000000000000000001410150000000000000000000000000000000000000000000000000000000000141016000000000000000000000000000000000000000000000000000000000014101700000000000000000000000000000000000000000000000000000000001410180000000000000000000000000000000000000000000000000000000000141019000000000000000000000000000000000000000000000000000000000014101a000000000000000000000000000000000000000000000000000000000014101b000000000000000000000000000000000000000000000000000000000014101c000000000000000000000000000000000000000000000000000000000014101d000000000000000000000000000000000000000000000000000000000014101e000000000000000000000000000000000000000000000000000000000014101f0000000000000000000000000000000000000000000000000000000000141020000000000000000000000000000000000000000000000000000000000014102100000000000000000000000000000000000000000000000000000000001410220000000000000000000000000000000000000000000000000000000000141023000000000000000000000000000000000000000000000000000000000014102400000000000000000000000000000000000000000000000000000000001410250000000000000000000000000000000000000000000000000000000000141026000000000000000000000000000000000000000000000000000000000014102700000000000000000000000000000000000000000000000000000000001410280000000000000000000000000000000000000000000000000000000000141029000000000000000000000000000000000000000000000000000000000014102a000000000000000000000000000000000000000000000000000000000014102b000000000000000000000000000000000000000000000000000000000014102c000000000000000000000000000000000000000000000000000000000014102d000000000000000000000000000000000000000000000000000000000014102e000000000000000000000000000000000000000000000000000000000014102f0000000000000000000000000000000000000000000000000000000000141030000000000000000000000000000000000000000000000000000000000014103100000000000000000000000000000000000000000000000000000000001410320000000000000000000000000000000000000000000000000000000000141033000000000000000000000000000000000000000000000000000000000014103400000000000000000000000000000000000000000000000000000000001410350000000000000000000000000000000000000000000000000000000000141036000000000000000000000000000000000000000000000000000000000014103700000000000000000000000000000000000000000000000000000000001410380000000000000000000000000000000000000000000000000000000000141039000000000000000000000000000000000000000000000000000000000014103a000000000000000000000000000000000000000000000000000000000014103b000000000000000000000000000000000000000000000000000000000014103c000000000000000000000000000000000000000000000000000000000014103d000000000000000000000000000000000000000000000000000000000014103e000000000000000000000000000000000000000000000000000000000014103f3f0000000000000000000000000000000000000000000000000000000000141100000000000000000000000000000000000000000000000000000000000014110100000000000000000000000000000000000000000000000000000000001411020000000000000000000000000000000000000000000000000000000000141103000000000000000000000000000000000000000000000000000000000014110400000000000000000000000000000000000000000000000000000000001411050000000000000000000000000000000000000000000000000000000000141106000000000000000000000000000000000000000000000000000000000014110700000000000000000000000000000000000000000000000000000000001411080000000000000000000000000000000000000000000000000000000000141109000000000000000000000000000000000000000000000000000000000014110a000000000000000000000000000000000000000000000000000000000014110b000000000000000000000000000000000000000000000000000000000014110c000000000000000000000000000000000000000000000000000000000014110d000000000000000000000000000000000000000000000000000000000014110e000000000000000000000000000000000000000000000000000000000014110f0000000000000000000000000000000000000000000000000000000000141110000000000000000000000000000000000000000000000000000000000014111100000000000000000000000000000000000000000000000000000000001411120000000000000000000000000000000000000000000000000000000000141113000000000000000000000000000000000000000000000000000000000014111400000000000000000000000000000000000000000000000000000000001411150000000000000000000000000000000000000000000000000000000000141116000000000000000000000000000000000000000000000000000000000014111700000000000000000000000000000000000000000000000000000000001411180000000000000000000000000000000000000000000000000000000000141119000000000000000000000000000000000000000000000000000000000014111a000000000000000000000000000000000000000000000000000000000014111b000000000000000000000000000000000000000000000000000000000014111c000000000000000000000000000000000000000000000000000000000014111d000000000000000000000000000000000000000000000000000000000014111e000000000000000000000000000000000000000000000000000000000014111f0000000000000000000000000000000000000000000000000000000000141120000000000000000000000000000000000000000000000000000000000014112100000000000000000000000000000000000000000000000000000000001411220000000000000000000000000000000000000000000000000000000000141123000000000000000000000000000000000000000000000000000000000014112400000000000000000000000000000000000000000000000000000000001411250000000000000000000000000000000000000000000000000000000000141126000000000000000000000000000000000000000000000000000000000014112700000000000000000000000000000000000000000000000000000000001411280000000000000000000000000000000000000000000000000000000000141129000000000000000000000000000000000000000000000000000000000014112a000000000000000000000000000000000000000000000000000000000014112b000000000000000000000000000000000000000000000000000000000014112c000000000000000000000000000000000000000000000000000000000014112d000000000000000000000000000000000000000000000000000000000014112e000000000000000000000000000000000000000000000000000000000014112f0000000000000000000000000000000000000000000000000000000000141130000000000000000000000000000000000000000000000000000000000014113100000000000000000000000000000000000000000000000000000000001411320000000000000000000000000000000000000000000000000000000000141133000000000000000000000000000000000000000000000000000000000014113400000000000000000000000000000000000000000000000000000000001411350000000000000000000000000000000000000000000000000000000000141136000000000000000000000000000000000000000000000000000000000014113700000000000000000000000000000000000000000000000000000000001411380000000000000000000000000000000000000000000000000000000000141139000000000000000000000000000000000000000000000000000000000014113a000000000000000000000000000000000000000000000000000000000014113b000000000000000000000000000000000000000000000000000000000014113c000000000000000000000000000000000000000000000000000000000014113d000000000000000000000000000000000000000000000000000000000014113e08005c015113cb57d67dd6c0febd596819ac0298b6a23fc80aba17d445d540059a00f20b7d1308051fe7b68031a7c336b0b4b56738928b6510133aff1b818d5a9a0063eec1883a4f95f4933f9275e850d84b3d035f5061ed986c437a07331fd30e00d3a32d6bbc4fd843686fd0c5e118a73b847529977dca5b9e0e81f6604f22ca00c2f4f5133d9194d41e853e5e951e16690babce8461f25342c0bad20f2aa1e3000a6bf4739e7eb387913d955dc2e8f14f8cce27696b9d2e128b6acefafb80ee005763f7e0648f958b559677622a648f318fc79ebc0cb539170d49c26456e69200302e2b8a92cda941e9af8761b89899a58a587656d9710594e1d865b16522993f0000000000000000000000000000000000000000000000000000000000142000000000000000000000000000000000000000000000000000000000000014200a0000000000000000000000000000000000000000000000000000000000142001000000000000000000000000000000000000000000000000000000000014200b0000000000000000000000000000000000000000000000000000000000142002000000000000000000000000000000000000000000000000000000000014200c0000000000000000000000000000000000000000000000000000000000142003000000000000000000000000000000000000000000000000000000000014200d0000000000000000000000000000000000000000000000000000000000142004000000000000000000000000000000000000000000000000000000000014200e0000000000000000000000000000000000000000000000000000000000142005000000000000000000000000000000000000000000000000000000000014200f00000000000000000000000000000000000000000000000000000000001420060000000000000000000000000000000000000000000000000000000000142010000000000000000000000000000000000000000000000000000000000014200700000000000000000000000000000000000000000000000000000000001420110000000000000000000000000000000000000000000000000000000000142008000000000000000000000000000000000000000000000000000000000014201200000000000000000000000000000000000000000000000000000000001420090000000000000000000000000000000000000000000000000000000000142013000000000000000000000000000000000000000000000000000000000014200a0000000000000000000000000000000000000000000000000000000000142014000000000000000000000000000000000000000000000000000000000014200b0000000000000000000000000000000000000000000000000000000000142015000000000000000000000000000000000000000000000000000000000014200c0000000000000000000000000000000000000000000000000000000000142016000000000000000000000000000000000000000000000000000000000014200d0000000000000000000000000000000000000000000000000000000000142017000000000000000000000000000000000000000000000000000000000014200e0000000000000000000000000000000000000000000000000000000000142018000000000000000000000000000000000000000000000000000000000014200f00000000000000000000000000000000000000000000000000000000001420190000000000000000000000000000000000000000000000000000000000142010000000000000000000000000000000000000000000000000000000000014201a0000000000000000000000000000000000000000000000000000000000142011000000000000000000000000000000000000000000000000000000000014201b0000000000000000000000000000000000000000000000000000000000142012000000000000000000000000000000000000000000000000000000000014201c0000000000000000000000000000000000000000000000000000000000142013000000000000000000000000000000000000000000000000000000000014201d0000000000000000000000000000000000000000000000000000000000142014000000000000000000000000000000000000000000000000000000000014201e0000000000000000000000000000000000000000000000000000000000142015000000000000000000000000000000000000000000000000000000000014201f00000000000000000000000000000000000000000000000000000000001420160000000000000000000000000000000000000000000000000000000000142020000000000000000000000000000000000000000000000000000000000014201700000000000000000000000000000000000000000000000000000000001420210000000000000000000000000000000000000000000000000000000000142018000000000000000000000000000000000000000000000000000000000014202200000000000000000000000000000000000000000000000000000000001420190000000000000000000000000000000000000000000000000000000000142023000000000000000000000000000000000000000000000000000000000014201a0000000000000000000000000000000000000000000000000000000000142024000000000000000000000000000000000000000000000000000000000014201b0000000000000000000000000000000000000000000000000000000000142025000000000000000000000000000000000000000000000000000000000014201c0000000000000000000000000000000000000000000000000000000000142026000000000000000000000000000000000000000000000000000000000014201d0000000000000000000000000000000000000000000000000000000000142027000000000000000000000000000000000000000000000000000000000014201e0000000000000000000000000000000000000000000000000000000000142028000000000000000000000000000000000000000000000000000000000014201f00000000000000000000000000000000000000000000000000000000001420290000000000000000000000000000000000000000000000000000000000142020000000000000000000000000000000000000000000000000000000000014202a0000000000000000000000000000000000000000000000000000000000142021000000000000000000000000000000000000000000000000000000000014202b0000000000000000000000000000000000000000000000000000000000142022000000000000000000000000000000000000000000000000000000000014202c0000000000000000000000000000000000000000000000000000000000142023000000000000000000000000000000000000000000000000000000000014202d0000000000000000000000000000000000000000000000000000000000142024000000000000000000000000000000000000000000000000000000000014202e0000000000000000000000000000000000000000000000000000000000142025000000000000000000000000000000000000000000000000000000000014202f00000000000000000000000000000000000000000000000000000000001420260000000000000000000000000000000000000000000000000000000000142030000000000000000000000000000000000000000000000000000000000014202700000000000000000000000000000000000000000000000000000000001420310000000000000000000000000000000000000000000000000000000000142028000000000000000000000000000000000000000000000000000000000014203200000000000000000000000000000000000000000000000000000000001420290000000000000000000000000000000000000000000000000000000000142033000000000000000000000000000000000000000000000000000000000014202a0000000000000000000000000000000000000000000000000000000000142034000000000000000000000000000000000000000000000000000000000014202b0000000000000000000000000000000000000000000000000000000000142035000000000000000000000000000000000000000000000000000000000014202c0000000000000000000000000000000000000000000000000000000000142036000000000000000000000000000000000000000000000000000000000014202d0000000000000000000000000000000000000000000000000000000000142037000000000000000000000000000000000000000000000000000000000014202e0000000000000000000000000000000000000000000000000000000000142038000000000000000000000000000000000000000000000000000000000014202f00000000000000000000000000000000000000000000000000000000001420390000000000000000000000000000000000000000000000000000000000142030000000000000000000000000000000000000000000000000000000000014203a0000000000000000000000000000000000000000000000000000000000142031000000000000000000000000000000000000000000000000000000000014203b0000000000000000000000000000000000000000000000000000000000142032000000000000000000000000000000000000000000000000000000000014203c0000000000000000000000000000000000000000000000000000000000142033000000000000000000000000000000000000000000000000000000000014203d0000000000000000000000000000000000000000000000000000000000142034000000000000000000000000000000000000000000000000000000000014203e0000000000000000000000000000000000000000000000000000000000142035000000000000000000000000000000000000000000000000000000000014203f00000000000000000000000000000000000000000000000000000000001420360000000000000000000000000000000000000000000000000000000000142040000000000000000000000000000000000000000000000000000000000014203700000000000000000000000000000000000000000000000000000000001420410000000000000000000000000000000000000000000000000000000000142038000000000000000000000000000000000000000000000000000000000014204200000000000000000000000000000000000000000000000000000000001420390000000000000000000000000000000000000000000000000000000000142043000000000000000000000000000000000000000000000000000000000014203a0000000000000000000000000000000000000000000000000000000000142044000000000000000000000000000000000000000000000000000000000014203b0000000000000000000000000000000000000000000000000000000000142045000000000000000000000000000000000000000000000000000000000014203c0000000000000000000000000000000000000000000000000000000000142046000000000000000000000000000000000000000000000000000000000014203d0000000000000000000000000000000000000000000000000000000000142047000000000000000000000000000000000000000000000000000000000014203e0000000000000000000000000000000000000000000000000000000000142048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000181000000000000000000000000000000000000000000000000000000000000018100100000000000000000000000000000000000000000000000000000000001810020000000000000000000000000000000000000000000000000000000000181003000000000000000000000000000000000000000000000000000000000018100400000000000000000000000000000000000000000000000000000000001810050000000000000000000000000000000000000000000000000000000000181006000000000000000000000000000000000000000000000000000000000018100700000000000000000000000000000000000000000000000000000000001810080000000000000000000000000000000000000000000000000000000000181009000000000000000000000000000000000000000000000000000000000018100a000000000000000000000000000000000000000000000000000000000018100b000000000000000000000000000000000000000000000000000000000018100c000000000000000000000000000000000000000000000000000000000018100d000000000000000000000000000000000000000000000000000000000018100e000000000000000000000000000000000000000000000000000000000018100f0000000000000000000000000000000000000000000000000000000000181010000000000000000000000000000000000000000000000000000000000018101100000000000000000000000000000000000000000000000000000000001810120000000000000000000000000000000000000000000000000000000000181013000000000000000000000000000000000000000000000000000000000018101400000000000000000000000000000000000000000000000000000000001810150000000000000000000000000000000000000000000000000000000000181016000000000000000000000000000000000000000000000000000000000018101700000000000000000000000000000000000000000000000000000000001810180000000000000000000000000000000000000000000000000000000000181019000000000000000000000000000000000000000000000000000000000018101a000000000000000000000000000000000000000000000000000000000018101b000000000000000000000000000000000000000000000000000000000018101c000000000000000000000000000000000000000000000000000000000018101d000000000000000000000000000000000000000000000000000000000018101e000000000000000000000000000000000000000000000000000000000018101f0000000000000000000000000000000000000000000000000000000000181020000000000000000000000000000000000000000000000000000000000018102100000000000000000000000000000000000000000000000000000000001810220000000000000000000000000000000000000000000000000000000000181023000000000000000000000000000000000000000000000000000000000018102400000000000000000000000000000000000000000000000000000000001810250000000000000000000000000000000000000000000000000000000000181026000000000000000000000000000000000000000000000000000000000018102700000000000000000000000000000000000000000000000000000000001810280000000000000000000000000000000000000000000000000000000000181029000000000000000000000000000000000000000000000000000000000018102a000000000000000000000000000000000000000000000000000000000018102b000000000000000000000000000000000000000000000000000000000018102c000000000000000000000000000000000000000000000000000000000018102d000000000000000000000000000000000000000000000000000000000018102e000000000000000000000000000000000000000000000000000000000018102f0000000000000000000000000000000000000000000000000000000000181030000000000000000000000000000000000000000000000000000000000018103100000000000000000000000000000000000000000000000000000000001810320000000000000000000000000000000000000000000000000000000000181033000000000000000000000000000000000000000000000000000000000018103400000000000000000000000000000000000000000000000000000000001810350000000000000000000000000000000000000000000000000000000000181036000000000000000000000000000000000000000000000000000000000018103700000000000000000000000000000000000000000000000000000000001810380000000000000000000000000000000000000000000000000000000000181039000000000000000000000000000000000000000000000000000000000018103a000000000000000000000000000000000000000000000000000000000018103b000000000000000000000000000000000000000000000000000000000018103c000000000000000000000000000000000000000000000000000000000018103d000000000000000000000000000000000000000000000000000000000018103e000000000000000000000000000000000000000000000000000000000018103f3f0000000000000000000000000000000000000000000000000000000000181100000000000000000000000000000000000000000000000000000000000018110100000000000000000000000000000000000000000000000000000000001811020000000000000000000000000000000000000000000000000000000000181103000000000000000000000000000000000000000000000000000000000018110400000000000000000000000000000000000000000000000000000000001811050000000000000000000000000000000000000000000000000000000000181106000000000000000000000000000000000000000000000000000000000018110700000000000000000000000000000000000000000000000000000000001811080000000000000000000000000000000000000000000000000000000000181109000000000000000000000000000000000000000000000000000000000018110a000000000000000000000000000000000000000000000000000000000018110b000000000000000000000000000000000000000000000000000000000018110c000000000000000000000000000000000000000000000000000000000018110d000000000000000000000000000000000000000000000000000000000018110e000000000000000000000000000000000000000000000000000000000018110f0000000000000000000000000000000000000000000000000000000000181110000000000000000000000000000000000000000000000000000000000018111100000000000000000000000000000000000000000000000000000000001811120000000000000000000000000000000000000000000000000000000000181113000000000000000000000000000000000000000000000000000000000018111400000000000000000000000000000000000000000000000000000000001811150000000000000000000000000000000000000000000000000000000000181116000000000000000000000000000000000000000000000000000000000018111700000000000000000000000000000000000000000000000000000000001811180000000000000000000000000000000000000000000000000000000000181119000000000000000000000000000000000000000000000000000000000018111a000000000000000000000000000000000000000000000000000000000018111b000000000000000000000000000000000000000000000000000000000018111c000000000000000000000000000000000000000000000000000000000018111d000000000000000000000000000000000000000000000000000000000018111e000000000000000000000000000000000000000000000000000000000018111f0000000000000000000000000000000000000000000000000000000000181120000000000000000000000000000000000000000000000000000000000018112100000000000000000000000000000000000000000000000000000000001811220000000000000000000000000000000000000000000000000000000000181123000000000000000000000000000000000000000000000000000000000018112400000000000000000000000000000000000000000000000000000000001811250000000000000000000000000000000000000000000000000000000000181126000000000000000000000000000000000000000000000000000000000018112700000000000000000000000000000000000000000000000000000000001811280000000000000000000000000000000000000000000000000000000000181129000000000000000000000000000000000000000000000000000000000018112a000000000000000000000000000000000000000000000000000000000018112b000000000000000000000000000000000000000000000000000000000018112c000000000000000000000000000000000000000000000000000000000018112d000000000000000000000000000000000000000000000000000000000018112e000000000000000000000000000000000000000000000000000000000018112f0000000000000000000000000000000000000000000000000000000000181130000000000000000000000000000000000000000000000000000000000018113100000000000000000000000000000000000000000000000000000000001811320000000000000000000000000000000000000000000000000000000000181133000000000000000000000000000000000000000000000000000000000018113400000000000000000000000000000000000000000000000000000000001811350000000000000000000000000000000000000000000000000000000000181136000000000000000000000000000000000000000000000000000000000018113700000000000000000000000000000000000000000000000000000000001811380000000000000000000000000000000000000000000000000000000000181139000000000000000000000000000000000000000000000000000000000018113a000000000000000000000000000000000000000000000000000000000018113b000000000000000000000000000000000000000000000000000000000018113c000000000000000000000000000000000000000000000000000000000018113d000000000000000000000000000000000000000000000000000000000018113e0800f872eb9653f03af10f331da1361fa1524d3cd958cb72dacea1d424f19df3af00ffc548a17cd6ba1f2d228f30e4ddb19ecc46ad3b609977d52bb0f49e1206410032f8058bd779c520eabae2743b02ec4f71670428506fcceb2d4b69f26fb11800c0283e15fbf74ffa4eafb984030394f3c2ea6733cc0eacb0431a9475eff28f00b7f55314bfd9d441c1c624e241908228fe4da3d3a0a7fbd56814e1c8cd5d3e00f430f33a786675271736fd728c7bf7428b8c24ac948d7faf76ddb8783a496c0048fc235ead8d4b9d44929662a6384074fc4e5076bec5b7deb34f612393684300fd9b61cb1ad9b4b28f58399906e73933e3cccee8fc98a393f0eedb95b13ee63f0000000000000000000000000000000000000000000000000000000000182000000000000000000000000000000000000000000000000000000000000018200a0000000000000000000000000000000000000000000000000000000000182001000000000000000000000000000000000000000000000000000000000018200b0000000000000000000000000000000000000000000000000000000000182002000000000000000000000000000000000000000000000000000000000018200c0000000000000000000000000000000000000000000000000000000000182003000000000000000000000000000000000000000000000000000000000018200d0000000000000000000000000000000000000000000000000000000000182004000000000000000000000000000000000000000000000000000000000018200e0000000000000000000000000000000000000000000000000000000000182005000000000000000000000000000000000000000000000000000000000018200f00000000000000000000000000000000000000000000000000000000001820060000000000000000000000000000000000000000000000000000000000182010000000000000000000000000000000000000000000000000000000000018200700000000000000000000000000000000000000000000000000000000001820110000000000000000000000000000000000000000000000000000000000182008000000000000000000000000000000000000000000000000000000000018201200000000000000000000000000000000000000000000000000000000001820090000000000000000000000000000000000000000000000000000000000182013000000000000000000000000000000000000000000000000000000000018200a0000000000000000000000000000000000000000000000000000000000182014000000000000000000000000000000000000000000000000000000000018200b0000000000000000000000000000000000000000000000000000000000182015000000000000000000000000000000000000000000000000000000000018200c0000000000000000000000000000000000000000000000000000000000182016000000000000000000000000000000000000000000000000000000000018200d0000000000000000000000000000000000000000000000000000000000182017000000000000000000000000000000000000000000000000000000000018200e0000000000000000000000000000000000000000000000000000000000182018000000000000000000000000000000000000000000000000000000000018200f00000000000000000000000000000000000000000000000000000000001820190000000000000000000000000000000000000000000000000000000000182010000000000000000000000000000000000000000000000000000000000018201a0000000000000000000000000000000000000000000000000000000000182011000000000000000000000000000000000000000000000000000000000018201b0000000000000000000000000000000000000000000000000000000000182012000000000000000000000000000000000000000000000000000000000018201c0000000000000000000000000000000000000000000000000000000000182013000000000000000000000000000000000000000000000000000000000018201d0000000000000000000000000000000000000000000000000000000000182014000000000000000000000000000000000000000000000000000000000018201e0000000000000000000000000000000000000000000000000000000000182015000000000000000000000000000000000000000000000000000000000018201f00000000000000000000000000000000000000000000000000000000001820160000000000000000000000000000000000000000000000000000000000182020000000000000000000000000000000000000000000000000000000000018201700000000000000000000000000000000000000000000000000000000001820210000000000000000000000000000000000000000000000000000000000182018000000000000000000000000000000000000000000000000000000000018202200000000000000000000000000000000000000000000000000000000001820190000000000000000000000000000000000000000000000000000000000182023000000000000000000000000000000000000000000000000000000000018201a0000000000000000000000000000000000000000000000000000000000182024000000000000000000000000000000000000000000000000000000000018201b0000000000000000000000000000000000000000000000000000000000182025000000000000000000000000000000000000000000000000000000000018201c0000000000000000000000000000000000000000000000000000000000182026000000000000000000000000000000000000000000000000000000000018201d0000000000000000000000000000000000000000000000000000000000182027000000000000000000000000000000000000000000000000000000000018201e0000000000000000000000000000000000000000000000000000000000182028000000000000000000000000000000000000000000000000000000000018201f00000000000000000000000000000000000000000000000000000000001820290000000000000000000000000000000000000000000000000000000000182020000000000000000000000000000000000000000000000000000000000018202a0000000000000000000000000000000000000000000000000000000000182021000000000000000000000000000000000000000000000000000000000018202b0000000000000000000000000000000000000000000000000000000000182022000000000000000000000000000000000000000000000000000000000018202c0000000000000000000000000000000000000000000000000000000000182023000000000000000000000000000000000000000000000000000000000018202d0000000000000000000000000000000000000000000000000000000000182024000000000000000000000000000000000000000000000000000000000018202e0000000000000000000000000000000000000000000000000000000000182025000000000000000000000000000000000000000000000000000000000018202f00000000000000000000000000000000000000000000000000000000001820260000000000000000000000000000000000000000000000000000000000182030000000000000000000000000000000000000000000000000000000000018202700000000000000000000000000000000000000000000000000000000001820310000000000000000000000000000000000000000000000000000000000182028000000000000000000000000000000000000000000000000000000000018203200000000000000000000000000000000000000000000000000000000001820290000000000000000000000000000000000000000000000000000000000182033000000000000000000000000000000000000000000000000000000000018202a0000000000000000000000000000000000000000000000000000000000182034000000000000000000000000000000000000000000000000000000000018202b0000000000000000000000000000000000000000000000000000000000182035000000000000000000000000000000000000000000000000000000000018202c0000000000000000000000000000000000000000000000000000000000182036000000000000000000000000000000000000000000000000000000000018202d0000000000000000000000000000000000000000000000000000000000182037000000000000000000000000000000000000000000000000000000000018202e0000000000000000000000000000000000000000000000000000000000182038000000000000000000000000000000000000000000000000000000000018202f00000000000000000000000000000000000000000000000000000000001820390000000000000000000000000000000000000000000000000000000000182030000000000000000000000000000000000000000000000000000000000018203a0000000000000000000000000000000000000000000000000000000000182031000000000000000000000000000000000000000000000000000000000018203b0000000000000000000000000000000000000000000000000000000000182032000000000000000000000000000000000000000000000000000000000018203c0000000000000000000000000000000000000000000000000000000000182033000000000000000000000000000000000000000000000000000000000018203d0000000000000000000000000000000000000000000000000000000000182034000000000000000000000000000000000000000000000000000000000018203e0000000000000000000000000000000000000000000000000000000000182035000000000000000000000000000000000000000000000000000000000018203f00000000000000000000000000000000000000000000000000000000001820360000000000000000000000000000000000000000000000000000000000182040000000000000000000000000000000000000000000000000000000000018203700000000000000000000000000000000000000000000000000000000001820410000000000000000000000000000000000000000000000000000000000182038000000000000000000000000000000000000000000000000000000000018204200000000000000000000000000000000000000000000000000000000001820390000000000000000000000000000000000000000000000000000000000182043000000000000000000000000000000000000000000000000000000000018203a0000000000000000000000000000000000000000000000000000000000182044000000000000000000000000000000000000000000000000000000000018203b0000000000000000000000000000000000000000000000000000000000182045000000000000000000000000000000000000000000000000000000000018203c0000000000000000000000000000000000000000000000000000000000182046000000000000000000000000000000000000000000000000000000000018203d0000000000000000000000000000000000000000000000000000000000182047000000000000000000000000000000000000000000000000000000000018203e00000000000000000000000000000000000000000000000000000000001820480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000001c100000000000000000000000000000000000000000000000000000000000001c100100000000000000000000000000000000000000000000000000000000001c100200000000000000000000000000000000000000000000000000000000001c100300000000000000000000000000000000000000000000000000000000001c100400000000000000000000000000000000000000000000000000000000001c100500000000000000000000000000000000000000000000000000000000001c100600000000000000000000000000000000000000000000000000000000001c100700000000000000000000000000000000000000000000000000000000001c100800000000000000000000000000000000000000000000000000000000001c100900000000000000000000000000000000000000000000000000000000001c100a00000000000000000000000000000000000000000000000000000000001c100b00000000000000000000000000000000000000000000000000000000001c100c00000000000000000000000000000000000000000000000000000000001c100d00000000000000000000000000000000000000000000000000000000001c100e00000000000000000000000000000000000000000000000000000000001c100f00000000000000000000000000000000000000000000000000000000001c101000000000000000000000000000000000000000000000000000000000001c101100000000000000000000000000000000000000000000000000000000001c101200000000000000000000000000000000000000000000000000000000001c101300000000000000000000000000000000000000000000000000000000001c101400000000000000000000000000000000000000000000000000000000001c101500000000000000000000000000000000000000000000000000000000001c101600000000000000000000000000000000000000000000000000000000001c101700000000000000000000000000000000000000000000000000000000001c101800000000000000000000000000000000000000000000000000000000001c101900000000000000000000000000000000000000000000000000000000001c101a00000000000000000000000000000000000000000000000000000000001c101b00000000000000000000000000000000000000000000000000000000001c101c00000000000000000000000000000000000000000000000000000000001c101d00000000000000000000000000000000000000000000000000000000001c101e00000000000000000000000000000000000000000000000000000000001c101f00000000000000000000000000000000000000000000000000000000001c102000000000000000000000000000000000000000000000000000000000001c102100000000000000000000000000000000000000000000000000000000001c102200000000000000000000000000000000000000000000000000000000001c102300000000000000000000000000000000000000000000000000000000001c102400000000000000000000000000000000000000000000000000000000001c102500000000000000000000000000000000000000000000000000000000001c102600000000000000000000000000000000000000000000000000000000001c102700000000000000000000000000000000000000000000000000000000001c102800000000000000000000000000000000000000000000000000000000001c102900000000000000000000000000000000000000000000000000000000001c102a00000000000000000000000000000000000000000000000000000000001c102b00000000000000000000000000000000000000000000000000000000001c102c00000000000000000000000000000000000000000000000000000000001c102d00000000000000000000000000000000000000000000000000000000001c102e00000000000000000000000000000000000000000000000000000000001c102f00000000000000000000000000000000000000000000000000000000001c103000000000000000000000000000000000000000000000000000000000001c103100000000000000000000000000000000000000000000000000000000001c103200000000000000000000000000000000000000000000000000000000001c103300000000000000000000000000000000000000000000000000000000001c103400000000000000000000000000000000000000000000000000000000001c103500000000000000000000000000000000000000000000000000000000001c103600000000000000000000000000000000000000000000000000000000001c103700000000000000000000000000000000000000000000000000000000001c103800000000000000000000000000000000000000000000000000000000001c103900000000000000000000000000000000000000000000000000000000001c103a00000000000000000000000000000000000000000000000000000000001c103b00000000000000000000000000000000000000000000000000000000001c103c00000000000000000000000000000000000000000000000000000000001c103d00000000000000000000000000000000000000000000000000000000001c103e00000000000000000000000000000000000000000000000000000000001c103f3f00000000000000000000000000000000000000000000000000000000001c110000000000000000000000000000000000000000000000000000000000001c110100000000000000000000000000000000000000000000000000000000001c110200000000000000000000000000000000000000000000000000000000001c110300000000000000000000000000000000000000000000000000000000001c110400000000000000000000000000000000000000000000000000000000001c110500000000000000000000000000000000000000000000000000000000001c110600000000000000000000000000000000000000000000000000000000001c110700000000000000000000000000000000000000000000000000000000001c110800000000000000000000000000000000000000000000000000000000001c110900000000000000000000000000000000000000000000000000000000001c110a00000000000000000000000000000000000000000000000000000000001c110b00000000000000000000000000000000000000000000000000000000001c110c00000000000000000000000000000000000000000000000000000000001c110d00000000000000000000000000000000000000000000000000000000001c110e00000000000000000000000000000000000000000000000000000000001c110f00000000000000000000000000000000000000000000000000000000001c111000000000000000000000000000000000000000000000000000000000001c111100000000000000000000000000000000000000000000000000000000001c111200000000000000000000000000000000000000000000000000000000001c111300000000000000000000000000000000000000000000000000000000001c111400000000000000000000000000000000000000000000000000000000001c111500000000000000000000000000000000000000000000000000000000001c111600000000000000000000000000000000000000000000000000000000001c111700000000000000000000000000000000000000000000000000000000001c111800000000000000000000000000000000000000000000000000000000001c111900000000000000000000000000000000000000000000000000000000001c111a00000000000000000000000000000000000000000000000000000000001c111b00000000000000000000000000000000000000000000000000000000001c111c00000000000000000000000000000000000000000000000000000000001c111d00000000000000000000000000000000000000000000000000000000001c111e00000000000000000000000000000000000000000000000000000000001c111f00000000000000000000000000000000000000000000000000000000001c112000000000000000000000000000000000000000000000000000000000001c112100000000000000000000000000000000000000000000000000000000001c112200000000000000000000000000000000000000000000000000000000001c112300000000000000000000000000000000000000000000000000000000001c112400000000000000000000000000000000000000000000000000000000001c112500000000000000000000000000000000000000000000000000000000001c112600000000000000000000000000000000000000000000000000000000001c112700000000000000000000000000000000000000000000000000000000001c112800000000000000000000000000000000000000000000000000000000001c112900000000000000000000000000000000000000000000000000000000001c112a00000000000000000000000000000000000000000000000000000000001c112b00000000000000000000000000000000000000000000000000000000001c112c00000000000000000000000000000000000000000000000000000000001c112d00000000000000000000000000000000000000000000000000000000001c112e00000000000000000000000000000000000000000000000000000000001c112f00000000000000000000000000000000000000000000000000000000001c113000000000000000000000000000000000000000000000000000000000001c113100000000000000000000000000000000000000000000000000000000001c113200000000000000000000000000000000000000000000000000000000001c113300000000000000000000000000000000000000000000000000000000001c113400000000000000000000000000000000000000000000000000000000001c113500000000000000000000000000000000000000000000000000000000001c113600000000000000000000000000000000000000000000000000000000001c113700000000000000000000000000000000000000000000000000000000001c113800000000000000000000000000000000000000000000000000000000001c113900000000000000000000000000000000000000000000000000000000001c113a00000000000000000000000000000000000000000000000000000000001c113b00000000000000000000000000000000000000000000000000000000001c113c00000000000000000000000000000000000000000000000000000000001c113d00000000000000000000000000000000000000000000000000000000001c113e08006838aa99533bea0d4204cad17cb3c147e99c2f9089e54a4289d54733eeada2002ab314bd11ace2494a3fb0970d276da39f0fe7da19c9a2438b9c7c334d32470071703d79d8425a7eca52006df6a8f9728508a83639e3e1c2ebae2b853a087c00c9501ac04a78ac5413c9131b08708064ed2c2515b8893f12c2d1cda15a44f100a0955f93e109778d26f9e5b0d46e45c539e59b0941517bfa888eb2d7d2d8a6005adc3be9406cc5f102c6adb44746e8529a256e2396353a8659344cc3e914c4007a5fe572cf6af804f472dabf095c5eb6b30efc5fd627ad3245a8ef0f3f578c003dcaa91dfc9fdad7ba8da68a48fc662dfc0a995cbb0c1bc62099c8257d240d3f00000000000000000000000000000000000000000000000000000000001c200000000000000000000000000000000000000000000000000000000000001c200a00000000000000000000000000000000000000000000000000000000001c200100000000000000000000000000000000000000000000000000000000001c200b00000000000000000000000000000000000000000000000000000000001c200200000000000000000000000000000000000000000000000000000000001c200c00000000000000000000000000000000000000000000000000000000001c200300000000000000000000000000000000000000000000000000000000001c200d00000000000000000000000000000000000000000000000000000000001c200400000000000000000000000000000000000000000000000000000000001c200e00000000000000000000000000000000000000000000000000000000001c200500000000000000000000000000000000000000000000000000000000001c200f00000000000000000000000000000000000000000000000000000000001c200600000000000000000000000000000000000000000000000000000000001c201000000000000000000000000000000000000000000000000000000000001c200700000000000000000000000000000000000000000000000000000000001c201100000000000000000000000000000000000000000000000000000000001c200800000000000000000000000000000000000000000000000000000000001c201200000000000000000000000000000000000000000000000000000000001c200900000000000000000000000000000000000000000000000000000000001c201300000000000000000000000000000000000000000000000000000000001c200a00000000000000000000000000000000000000000000000000000000001c201400000000000000000000000000000000000000000000000000000000001c200b00000000000000000000000000000000000000000000000000000000001c201500000000000000000000000000000000000000000000000000000000001c200c00000000000000000000000000000000000000000000000000000000001c201600000000000000000000000000000000000000000000000000000000001c200d00000000000000000000000000000000000000000000000000000000001c201700000000000000000000000000000000000000000000000000000000001c200e00000000000000000000000000000000000000000000000000000000001c201800000000000000000000000000000000000000000000000000000000001c200f00000000000000000000000000000000000000000000000000000000001c201900000000000000000000000000000000000000000000000000000000001c201000000000000000000000000000000000000000000000000000000000001c201a00000000000000000000000000000000000000000000000000000000001c201100000000000000000000000000000000000000000000000000000000001c201b00000000000000000000000000000000000000000000000000000000001c201200000000000000000000000000000000000000000000000000000000001c201c00000000000000000000000000000000000000000000000000000000001c201300000000000000000000000000000000000000000000000000000000001c201d00000000000000000000000000000000000000000000000000000000001c201400000000000000000000000000000000000000000000000000000000001c201e00000000000000000000000000000000000000000000000000000000001c201500000000000000000000000000000000000000000000000000000000001c201f00000000000000000000000000000000000000000000000000000000001c201600000000000000000000000000000000000000000000000000000000001c202000000000000000000000000000000000000000000000000000000000001c201700000000000000000000000000000000000000000000000000000000001c202100000000000000000000000000000000000000000000000000000000001c201800000000000000000000000000000000000000000000000000000000001c202200000000000000000000000000000000000000000000000000000000001c201900000000000000000000000000000000000000000000000000000000001c202300000000000000000000000000000000000000000000000000000000001c201a00000000000000000000000000000000000000000000000000000000001c202400000000000000000000000000000000000000000000000000000000001c201b00000000000000000000000000000000000000000000000000000000001c202500000000000000000000000000000000000000000000000000000000001c201c00000000000000000000000000000000000000000000000000000000001c202600000000000000000000000000000000000000000000000000000000001c201d00000000000000000000000000000000000000000000000000000000001c202700000000000000000000000000000000000000000000000000000000001c201e00000000000000000000000000000000000000000000000000000000001c202800000000000000000000000000000000000000000000000000000000001c201f00000000000000000000000000000000000000000000000000000000001c202900000000000000000000000000000000000000000000000000000000001c202000000000000000000000000000000000000000000000000000000000001c202a00000000000000000000000000000000000000000000000000000000001c202100000000000000000000000000000000000000000000000000000000001c202b00000000000000000000000000000000000000000000000000000000001c202200000000000000000000000000000000000000000000000000000000001c202c00000000000000000000000000000000000000000000000000000000001c202300000000000000000000000000000000000000000000000000000000001c202d00000000000000000000000000000000000000000000000000000000001c202400000000000000000000000000000000000000000000000000000000001c202e00000000000000000000000000000000000000000000000000000000001c202500000000000000000000000000000000000000000000000000000000001c202f00000000000000000000000000000000000000000000000000000000001c202600000000000000000000000000000000000000000000000000000000001c203000000000000000000000000000000000000000000000000000000000001c202700000000000000000000000000000000000000000000000000000000001c203100000000000000000000000000000000000000000000000000000000001c202800000000000000000000000000000000000000000000000000000000001c203200000000000000000000000000000000000000000000000000000000001c202900000000000000000000000000000000000000000000000000000000001c203300000000000000000000000000000000000000000000000000000000001c202a00000000000000000000000000000000000000000000000000000000001c203400000000000000000000000000000000000000000000000000000000001c202b00000000000000000000000000000000000000000000000000000000001c203500000000000000000000000000000000000000000000000000000000001c202c00000000000000000000000000000000000000000000000000000000001c203600000000000000000000000000000000000000000000000000000000001c202d00000000000000000000000000000000000000000000000000000000001c203700000000000000000000000000000000000000000000000000000000001c202e00000000000000000000000000000000000000000000000000000000001c203800000000000000000000000000000000000000000000000000000000001c202f00000000000000000000000000000000000000000000000000000000001c203900000000000000000000000000000000000000000000000000000000001c203000000000000000000000000000000000000000000000000000000000001c203a00000000000000000000000000000000000000000000000000000000001c203100000000000000000000000000000000000000000000000000000000001c203b00000000000000000000000000000000000000000000000000000000001c203200000000000000000000000000000000000000000000000000000000001c203c00000000000000000000000000000000000000000000000000000000001c203300000000000000000000000000000000000000000000000000000000001c203d00000000000000000000000000000000000000000000000000000000001c203400000000000000000000000000000000000000000000000000000000001c203e00000000000000000000000000000000000000000000000000000000001c203500000000000000000000000000000000000000000000000000000000001c203f00000000000000000000000000000000000000000000000000000000001c203600000000000000000000000000000000000000000000000000000000001c204000000000000000000000000000000000000000000000000000000000001c203700000000000000000000000000000000000000000000000000000000001c204100000000000000000000000000000000000000000000000000000000001c203800000000000000000000000000000000000000000000000000000000001c204200000000000000000000000000000000000000000000000000000000001c203900000000000000000000000000000000000000000000000000000000001c204300000000000000000000000000000000000000000000000000000000001c203a00000000000000000000000000000000000000000000000000000000001c204400000000000000000000000000000000000000000000000000000000001c203b00000000000000000000000000000000000000000000000000000000001c204500000000000000000000000000000000000000000000000000000000001c203c00000000000000000000000000000000000000000000000000000000001c204600000000000000000000000000000000000000000000000000000000001c203d00000000000000000000000000000000000000000000000000000000001c204700000000000000000000000000000000000000000000000000000000001c203e00000000000000000000000000000000000000000000000000000000001c2048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000201000000000000000000000000000000000000000000000000000000000000020100100000000000000000000000000000000000000000000000000000000002010020000000000000000000000000000000000000000000000000000000000201003000000000000000000000000000000000000000000000000000000000020100400000000000000000000000000000000000000000000000000000000002010050000000000000000000000000000000000000000000000000000000000201006000000000000000000000000000000000000000000000000000000000020100700000000000000000000000000000000000000000000000000000000002010080000000000000000000000000000000000000000000000000000000000201009000000000000000000000000000000000000000000000000000000000020100a000000000000000000000000000000000000000000000000000000000020100b000000000000000000000000000000000000000000000000000000000020100c000000000000000000000000000000000000000000000000000000000020100d000000000000000000000000000000000000000000000000000000000020100e000000000000000000000000000000000000000000000000000000000020100f0000000000000000000000000000000000000000000000000000000000201010000000000000000000000000000000000000000000000000000000000020101100000000000000000000000000000000000000000000000000000000002010120000000000000000000000000000000000000000000000000000000000201013000000000000000000000000000000000000000000000000000000000020101400000000000000000000000000000000000000000000000000000000002010150000000000000000000000000000000000000000000000000000000000201016000000000000000000000000000000000000000000000000000000000020101700000000000000000000000000000000000000000000000000000000002010180000000000000000000000000000000000000000000000000000000000201019000000000000000000000000000000000000000000000000000000000020101a000000000000000000000000000000000000000000000000000000000020101b000000000000000000000000000000000000000000000000000000000020101c000000000000000000000000000000000000000000000000000000000020101d000000000000000000000000000000000000000000000000000000000020101e000000000000000000000000000000000000000000000000000000000020101f0000000000000000000000000000000000000000000000000000000000201020000000000000000000000000000000000000000000000000000000000020102100000000000000000000000000000000000000000000000000000000002010220000000000000000000000000000000000000000000000000000000000201023000000000000000000000000000000000000000000000000000000000020102400000000000000000000000000000000000000000000000000000000002010250000000000000000000000000000000000000000000000000000000000201026000000000000000000000000000000000000000000000000000000000020102700000000000000000000000000000000000000000000000000000000002010280000000000000000000000000000000000000000000000000000000000201029000000000000000000000000000000000000000000000000000000000020102a000000000000000000000000000000000000000000000000000000000020102b000000000000000000000000000000000000000000000000000000000020102c000000000000000000000000000000000000000000000000000000000020102d000000000000000000000000000000000000000000000000000000000020102e000000000000000000000000000000000000000000000000000000000020102f0000000000000000000000000000000000000000000000000000000000201030000000000000000000000000000000000000000000000000000000000020103100000000000000000000000000000000000000000000000000000000002010320000000000000000000000000000000000000000000000000000000000201033000000000000000000000000000000000000000000000000000000000020103400000000000000000000000000000000000000000000000000000000002010350000000000000000000000000000000000000000000000000000000000201036000000000000000000000000000000000000000000000000000000000020103700000000000000000000000000000000000000000000000000000000002010380000000000000000000000000000000000000000000000000000000000201039000000000000000000000000000000000000000000000000000000000020103a000000000000000000000000000000000000000000000000000000000020103b000000000000000000000000000000000000000000000000000000000020103c000000000000000000000000000000000000000000000000000000000020103d000000000000000000000000000000000000000000000000000000000020103e000000000000000000000000000000000000000000000000000000000020103f3f0000000000000000000000000000000000000000000000000000000000201100000000000000000000000000000000000000000000000000000000000020110100000000000000000000000000000000000000000000000000000000002011020000000000000000000000000000000000000000000000000000000000201103000000000000000000000000000000000000000000000000000000000020110400000000000000000000000000000000000000000000000000000000002011050000000000000000000000000000000000000000000000000000000000201106000000000000000000000000000000000000000000000000000000000020110700000000000000000000000000000000000000000000000000000000002011080000000000000000000000000000000000000000000000000000000000201109000000000000000000000000000000000000000000000000000000000020110a000000000000000000000000000000000000000000000000000000000020110b000000000000000000000000000000000000000000000000000000000020110c000000000000000000000000000000000000000000000000000000000020110d000000000000000000000000000000000000000000000000000000000020110e000000000000000000000000000000000000000000000000000000000020110f0000000000000000000000000000000000000000000000000000000000201110000000000000000000000000000000000000000000000000000000000020111100000000000000000000000000000000000000000000000000000000002011120000000000000000000000000000000000000000000000000000000000201113000000000000000000000000000000000000000000000000000000000020111400000000000000000000000000000000000000000000000000000000002011150000000000000000000000000000000000000000000000000000000000201116000000000000000000000000000000000000000000000000000000000020111700000000000000000000000000000000000000000000000000000000002011180000000000000000000000000000000000000000000000000000000000201119000000000000000000000000000000000000000000000000000000000020111a000000000000000000000000000000000000000000000000000000000020111b000000000000000000000000000000000000000000000000000000000020111c000000000000000000000000000000000000000000000000000000000020111d000000000000000000000000000000000000000000000000000000000020111e000000000000000000000000000000000000000000000000000000000020111f0000000000000000000000000000000000000000000000000000000000201120000000000000000000000000000000000000000000000000000000000020112100000000000000000000000000000000000000000000000000000000002011220000000000000000000000000000000000000000000000000000000000201123000000000000000000000000000000000000000000000000000000000020112400000000000000000000000000000000000000000000000000000000002011250000000000000000000000000000000000000000000000000000000000201126000000000000000000000000000000000000000000000000000000000020112700000000000000000000000000000000000000000000000000000000002011280000000000000000000000000000000000000000000000000000000000201129000000000000000000000000000000000000000000000000000000000020112a000000000000000000000000000000000000000000000000000000000020112b000000000000000000000000000000000000000000000000000000000020112c000000000000000000000000000000000000000000000000000000000020112d000000000000000000000000000000000000000000000000000000000020112e000000000000000000000000000000000000000000000000000000000020112f0000000000000000000000000000000000000000000000000000000000201130000000000000000000000000000000000000000000000000000000000020113100000000000000000000000000000000000000000000000000000000002011320000000000000000000000000000000000000000000000000000000000201133000000000000000000000000000000000000000000000000000000000020113400000000000000000000000000000000000000000000000000000000002011350000000000000000000000000000000000000000000000000000000000201136000000000000000000000000000000000000000000000000000000000020113700000000000000000000000000000000000000000000000000000000002011380000000000000000000000000000000000000000000000000000000000201139000000000000000000000000000000000000000000000000000000000020113a000000000000000000000000000000000000000000000000000000000020113b000000000000000000000000000000000000000000000000000000000020113c000000000000000000000000000000000000000000000000000000000020113d000000000000000000000000000000000000000000000000000000000020113e0800e9805e8a4faa87fc419af08a6d956f18976c46ea694bbd4cf6946e6d02033200e0925a6b172b4b01bb76eb1d3f7dd2ced118bca70d223a6d61afa1b75915ae00383590492d2f99a0283d1de57015b4b6b0759a8023af2c68fb4929dee2f303007ed57100dd77e2b6405f780503ef61b7b53e13f344b6e6a6eff3e3c13de0d0001ab1b0c348c46184dbc86ff79f248e7da1b09d3f9c6a986e98fe45389f060d0023d134bc68d7efa25e255001069827dc0bee766c08c988d6300071ed27fe6c0031cbb780b07f632cbaf767dc80608cc0a8e1d1df3ecd6f5d8bc0ca6703e4f4002c7dc9e731fc5f6456b2a70b4e636ac17d5e0cd36d3a591116a9e124f735863f0000000000000000000000000000000000000000000000000000000000202000000000000000000000000000000000000000000000000000000000000020200a0000000000000000000000000000000000000000000000000000000000202001000000000000000000000000000000000000000000000000000000000020200b0000000000000000000000000000000000000000000000000000000000202002000000000000000000000000000000000000000000000000000000000020200c0000000000000000000000000000000000000000000000000000000000202003000000000000000000000000000000000000000000000000000000000020200d0000000000000000000000000000000000000000000000000000000000202004000000000000000000000000000000000000000000000000000000000020200e0000000000000000000000000000000000000000000000000000000000202005000000000000000000000000000000000000000000000000000000000020200f00000000000000000000000000000000000000000000000000000000002020060000000000000000000000000000000000000000000000000000000000202010000000000000000000000000000000000000000000000000000000000020200700000000000000000000000000000000000000000000000000000000002020110000000000000000000000000000000000000000000000000000000000202008000000000000000000000000000000000000000000000000000000000020201200000000000000000000000000000000000000000000000000000000002020090000000000000000000000000000000000000000000000000000000000202013000000000000000000000000000000000000000000000000000000000020200a0000000000000000000000000000000000000000000000000000000000202014000000000000000000000000000000000000000000000000000000000020200b0000000000000000000000000000000000000000000000000000000000202015000000000000000000000000000000000000000000000000000000000020200c0000000000000000000000000000000000000000000000000000000000202016000000000000000000000000000000000000000000000000000000000020200d0000000000000000000000000000000000000000000000000000000000202017000000000000000000000000000000000000000000000000000000000020200e0000000000000000000000000000000000000000000000000000000000202018000000000000000000000000000000000000000000000000000000000020200f00000000000000000000000000000000000000000000000000000000002020190000000000000000000000000000000000000000000000000000000000202010000000000000000000000000000000000000000000000000000000000020201a0000000000000000000000000000000000000000000000000000000000202011000000000000000000000000000000000000000000000000000000000020201b0000000000000000000000000000000000000000000000000000000000202012000000000000000000000000000000000000000000000000000000000020201c0000000000000000000000000000000000000000000000000000000000202013000000000000000000000000000000000000000000000000000000000020201d0000000000000000000000000000000000000000000000000000000000202014000000000000000000000000000000000000000000000000000000000020201e0000000000000000000000000000000000000000000000000000000000202015000000000000000000000000000000000000000000000000000000000020201f00000000000000000000000000000000000000000000000000000000002020160000000000000000000000000000000000000000000000000000000000202020000000000000000000000000000000000000000000000000000000000020201700000000000000000000000000000000000000000000000000000000002020210000000000000000000000000000000000000000000000000000000000202018000000000000000000000000000000000000000000000000000000000020202200000000000000000000000000000000000000000000000000000000002020190000000000000000000000000000000000000000000000000000000000202023000000000000000000000000000000000000000000000000000000000020201a0000000000000000000000000000000000000000000000000000000000202024000000000000000000000000000000000000000000000000000000000020201b0000000000000000000000000000000000000000000000000000000000202025000000000000000000000000000000000000000000000000000000000020201c0000000000000000000000000000000000000000000000000000000000202026000000000000000000000000000000000000000000000000000000000020201d0000000000000000000000000000000000000000000000000000000000202027000000000000000000000000000000000000000000000000000000000020201e0000000000000000000000000000000000000000000000000000000000202028000000000000000000000000000000000000000000000000000000000020201f00000000000000000000000000000000000000000000000000000000002020290000000000000000000000000000000000000000000000000000000000202020000000000000000000000000000000000000000000000000000000000020202a0000000000000000000000000000000000000000000000000000000000202021000000000000000000000000000000000000000000000000000000000020202b0000000000000000000000000000000000000000000000000000000000202022000000000000000000000000000000000000000000000000000000000020202c0000000000000000000000000000000000000000000000000000000000202023000000000000000000000000000000000000000000000000000000000020202d0000000000000000000000000000000000000000000000000000000000202024000000000000000000000000000000000000000000000000000000000020202e0000000000000000000000000000000000000000000000000000000000202025000000000000000000000000000000000000000000000000000000000020202f00000000000000000000000000000000000000000000000000000000002020260000000000000000000000000000000000000000000000000000000000202030000000000000000000000000000000000000000000000000000000000020202700000000000000000000000000000000000000000000000000000000002020310000000000000000000000000000000000000000000000000000000000202028000000000000000000000000000000000000000000000000000000000020203200000000000000000000000000000000000000000000000000000000002020290000000000000000000000000000000000000000000000000000000000202033000000000000000000000000000000000000000000000000000000000020202a0000000000000000000000000000000000000000000000000000000000202034000000000000000000000000000000000000000000000000000000000020202b0000000000000000000000000000000000000000000000000000000000202035000000000000000000000000000000000000000000000000000000000020202c0000000000000000000000000000000000000000000000000000000000202036000000000000000000000000000000000000000000000000000000000020202d0000000000000000000000000000000000000000000000000000000000202037000000000000000000000000000000000000000000000000000000000020202e0000000000000000000000000000000000000000000000000000000000202038000000000000000000000000000000000000000000000000000000000020202f00000000000000000000000000000000000000000000000000000000002020390000000000000000000000000000000000000000000000000000000000202030000000000000000000000000000000000000000000000000000000000020203a0000000000000000000000000000000000000000000000000000000000202031000000000000000000000000000000000000000000000000000000000020203b0000000000000000000000000000000000000000000000000000000000202032000000000000000000000000000000000000000000000000000000000020203c0000000000000000000000000000000000000000000000000000000000202033000000000000000000000000000000000000000000000000000000000020203d0000000000000000000000000000000000000000000000000000000000202034000000000000000000000000000000000000000000000000000000000020203e0000000000000000000000000000000000000000000000000000000000202035000000000000000000000000000000000000000000000000000000000020203f00000000000000000000000000000000000000000000000000000000002020360000000000000000000000000000000000000000000000000000000000202040000000000000000000000000000000000000000000000000000000000020203700000000000000000000000000000000000000000000000000000000002020410000000000000000000000000000000000000000000000000000000000202038000000000000000000000000000000000000000000000000000000000020204200000000000000000000000000000000000000000000000000000000002020390000000000000000000000000000000000000000000000000000000000202043000000000000000000000000000000000000000000000000000000000020203a0000000000000000000000000000000000000000000000000000000000202044000000000000000000000000000000000000000000000000000000000020203b0000000000000000000000000000000000000000000000000000000000202045000000000000000000000000000000000000000000000000000000000020203c0000000000000000000000000000000000000000000000000000000000202046000000000000000000000000000000000000000000000000000000000020203d0000000000000000000000000000000000000000000000000000000000202047000000000000000000000000000000000000000000000000000000000020203e0000000000000000000000000000000000000000000000000000000000202048000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "decodedHeader": { "contentCommitment": { - "blobHash": "0x00333b0e888900fb36313f16f33b652ec1a63d5264d2d20e320db603dc88b9eb", + "blobHash": "0x0019548bfa1ee2c5803e43176522f345aafcae12c1bda63371ed8b38c9d8e77b", "inHash": "0x00e1371045bd7d2c3e1f19cba5f536f0e82042ba4bc257d4ba19c146215e8242", "outHash": "0x009514581058b2b6aae79574cc9129a801904407c6d869a5f168b02cebffecfe", "numTxs": 8 @@ -104,10 +104,10 @@ "blockNumber": 2, "slotNumber": "0x0000000000000000000000000000000000000000000000000000000000000023", "chainId": 31337, - "timestamp": 1731602162, + "timestamp": 1731774882, "version": 1, - "coinbase": "0x04197076bf00abeee6a831983ef8302441add4ef", - "feeRecipient": "0x06b0da1b672bf6d9380e9553ff0985441795d437cdb5b685aba840453f8f46b0", + "coinbase": "0xcf4026defdbcf6d380561d2efbd56b77bb010b88", + "feeRecipient": "0x1d8e356ffb1a70658c67ac17b27be96faeab7707331b882e25a7a79c087ddcd1", "gasFees": { "feePerDaGas": 0, "feePerL2Gas": 0 @@ -115,7 +115,7 @@ }, "lastArchive": { "nextAvailableLeafIndex": 2, - "root": "0x0c8761d01984809bc7d2b22ad95919a63ecb26627391e6cc96e4c25db3dadc94" + "root": "0x1c33efe9cb9b002061f68be15b0c7ccc5fe4293ba4e1e6777862c2710ad8f6ee" }, "stateReference": { "l1ToL2MessageTree": { @@ -138,9 +138,9 @@ } } }, - "header": "0x0c8761d01984809bc7d2b22ad95919a63ecb26627391e6cc96e4c25db3dadc9400000002000000000000000000000000000000000000000000000000000000000000000800333b0e888900fb36313f16f33b652ec1a63d5264d2d20e320db603dc88b9eb00e1371045bd7d2c3e1f19cba5f536f0e82042ba4bc257d4ba19c146215e8242009514581058b2b6aae79574cc9129a801904407c6d869a5f168b02cebffecfe026efb6c2a517de2448119d0f1255757265dbec7cdd2952df929ede666e10944000000202494d2575971bca59a28ddc774d19136f4a294951ab67258c7e9c2d8f9805924000002002ed5c359f01d6a1cacfa324bc48b7fcc6fe75a95ad66bdb1a6e32d69075509570000028023a39db7c42fa47a6df2b9deea545155c39f6066cbbc2701a12c60af95b6cdf9000002800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002300000000000000000000000000000000000000000000000000000000673626f204197076bf00abeee6a831983ef8302441add4ef06b0da1b672bf6d9380e9553ff0985441795d437cdb5b685aba840453f8f46b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "publicInputsHash": "0x00b3ee26cefae7f16ddc9c2da9c1ce2cd052d1d05dd83fcacfe55e7d206721c1", - "blobPublicInputs": "0x01333b0e888900fb36313f16f33b652ec1a63d5264d2d20e320db603dc88b9eb060491159f212494d22ad4128924d49e6170152e9ff355aa2d483ddc2576b48a09866dad6c95c9d8b380d38c5383d86a34da4b7891cbd5129450bceb3b2508fd8c8f4fd73045913adc7f5af7c09522e72754ae7dc2e4b6b90ca99fe0a2123fe27eeb00db9be2d66001d55607eb36bf5d8d76cacb2f5e3f031aa6081d44376bbaf15b901b64459d5ae4e5af1b82a7ea266da9e84a516a76b9f3ecb63aab4fe3cb", + "header": "0x1c33efe9cb9b002061f68be15b0c7ccc5fe4293ba4e1e6777862c2710ad8f6ee0000000200000000000000000000000000000000000000000000000000000000000000080019548bfa1ee2c5803e43176522f345aafcae12c1bda63371ed8b38c9d8e77b00e1371045bd7d2c3e1f19cba5f536f0e82042ba4bc257d4ba19c146215e8242009514581058b2b6aae79574cc9129a801904407c6d869a5f168b02cebffecfe026efb6c2a517de2448119d0f1255757265dbec7cdd2952df929ede666e10944000000202494d2575971bca59a28ddc774d19136f4a294951ab67258c7e9c2d8f9805924000002002ed5c359f01d6a1cacfa324bc48b7fcc6fe75a95ad66bdb1a6e32d69075509570000028023a39db7c42fa47a6df2b9deea545155c39f6066cbbc2701a12c60af95b6cdf9000002800000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000023000000000000000000000000000000000000000000000000000000006738c9a2cf4026defdbcf6d380561d2efbd56b77bb010b881d8e356ffb1a70658c67ac17b27be96faeab7707331b882e25a7a79c087ddcd1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "publicInputsHash": "0x000445cc1c392d84934d7cee4af152a5630a19a9cca272f783c9751e24686089", + "blobInputs": "0x0101333b0e888900fb36313f16f33b652ec1a63d5264d2d20e320db603dc88b9eb060491159f212494d22ad4128924d49e6170152e9ff355aa2d483ddc2576b48a09866dad6c95c9d8b380d38c5383d86a34da4b7891cbd5129450bceb3b2508fd8c8f4fd73045913adc7f5af7c09522e72754ae7dc2e4b6b90ca99fe0a2123fe27eeb00db9be2d66001d55607eb36bf5d8d76cacb2f5e3f031aa6081d44376bbaf15b901b64459d5ae4e5af1b82a7ea266da9e84a516a76b9f3ecb63aab4fe3cb", "numTxs": 8 } } \ No newline at end of file diff --git a/l1-contracts/test/sparta/Sparta.t.sol b/l1-contracts/test/sparta/Sparta.t.sol index 43a12d1faa3..a9ed6212685 100644 --- a/l1-contracts/test/sparta/Sparta.t.sol +++ b/l1-contracts/test/sparta/Sparta.t.sol @@ -228,7 +228,7 @@ contract SpartaTest is DecoderBase { txHashes, signatures, full.block.body, - full.block.blobPublicInputs + full.block.blobInputs ); if (ree.shouldRevert) { @@ -243,7 +243,7 @@ contract SpartaTest is DecoderBase { txHashes, signatures, full.block.body, - full.block.blobPublicInputs + full.block.blobInputs ); } diff --git a/noir-projects/noir-protocol-circuits/crates/blob/Nargo.toml b/noir-projects/noir-protocol-circuits/crates/blob/Nargo.toml index 74351e76e3b..da49758490e 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/Nargo.toml +++ b/noir-projects/noir-protocol-circuits/crates/blob/Nargo.toml @@ -5,5 +5,5 @@ authors = [""] compiler_version = ">=0.30.0" [dependencies] -bigint = {tag = "v0.4.0", git = "https://github.com/noir-lang/noir-bignum" } +bigint = {tag = "v0.4.2", git = "https://github.com/noir-lang/noir-bignum" } types = { path = "../types" } diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr index 0719dff299f..d1d1c581a91 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr @@ -1,35 +1,26 @@ -// ONLY IMPORT ONE OF THESE CONFIGS! The big `config` takes 11 mins to compile. - -// SMALL CONFIG ********************************************************************************* - -// mod smaller_config; - -// use crate::smaller_config::{ -// BigNum, BLS12_381_Fr_Params, F, FIELDS_PER_BLOB, LOG_FIELDS_PER_BLOB, NOIR_FIELDS_PER_BLOB, -// FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB, D, D_INV, ROOTS, NEGATIVE_ROOTS -// }; - -//********************************************************************************* - -// BIG CONFIG ********************************************************************* - +// TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. use crate::{ - blob_public_inputs::BlobPublicInputs, - config::{ - D, D_INV, F, FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB, LOG_FIELDS_PER_BLOB, - NOIR_FIELDS_PER_BLOB, ROOTS, + blob_public_inputs::{BlobCommitment, BlobPublicInputs, BlockBlobPublicInputs}, + unconstrained_config::{ + compute_roots_of_unity, D, D_INV, F, FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB, + LOG_FIELDS_PER_BLOB, NOIR_FIELDS_PER_BLOB, }, }; -//********************************************************************************* -use bigint::{BigNum, fields::bls12_381Fr::BLS12_381_Fr_Params}; +use bigint::BigNum; // Fixed hash method: use types::hash::poseidon2_hash_subarray; // Variable hash method: // use types::hash::poseidon2_cheaper_variable_hash; -use types::{abis::sponge_blob::SpongeBlob, constants::FIELDS_PER_BLOB}; +use types::{ + abis::sponge_blob::SpongeBlob, + constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, + utils::arrays::array_splice, +}; -global LIMB_MAX = 2.pow_32(120); +global LIMB_MAX = 0x1000000000000000000000000000000; // 2^120 +global TWO_POW_56: u64 = 0x100000000000000; // u64 to aid integer only modulo in __field_to_bignum_limbs +global TWO_POW_64: Field = 0x10000000000000000; unconstrained fn __batch_invert_impl(mut x: [F; N]) -> [F; N] { let mut accumulator: F = BigNum::one(); @@ -55,39 +46,35 @@ unconstrained fn __batch_invert_impl(mut x: [F; N]) -> [F; N] { x } -// Not used because it resulted in "stack too deep", so it's inlined instead. -unconstrained fn __compute_fracs(z: F, ys: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { - let mut denoms: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; - for i in 0..FIELDS_PER_BLOB { - denoms[i] = z.__add(ROOTS[i].neg()); // (z - omega^i) - } - let inv_denoms = __batch_invert_impl(denoms); // 1 / (z - omega^i), for all i - let mut fracs: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; - for i in 0..FIELDS_PER_BLOB { - let inv_denom = inv_denoms[i]; // 1 / (z - omega^i) - fracs[i] = ys[i].__mul(inv_denom); // y_i / (z - omega^i) - } - fracs -} +// Taken from https://github.com/iAmMichaelConnor/blob-lib/blob/main/noir-circuits/blob/src/main.nr +unconstrained fn __field_to_bignum_limbs(x: Field) -> [Field; 3] { + // Here we're taking advantage of truncating 64 bit limbs from the input field + // and then subtracting them from the input such that the field division is equivalent to integer division. + let low_120_lower_64 = (x as u64) as Field; + let x_shifted_64 = (x - low_120_lower_64) / TWO_POW_64; + let low_120_upper_56 = ((x_shifted_64 as u64) % TWO_POW_56) as Field; + let low_120 = low_120_lower_64 + TWO_POW_64 * low_120_upper_56; -unconstrained fn __field_to_bytes(x: Field) -> [u8; 32] { - x.to_be_bytes() -} + let x_shifted_120 = (x_shifted_64 - low_120_upper_56) / (TWO_POW_56 as Field); -unconstrained fn __field_to_bignum(x: Field) -> F { - let x_bytes = __field_to_bytes(x); + let mid_120_lower_64 = (x_shifted_120 as u64) as Field; + let x_shifted_184 = (x_shifted_120 - mid_120_lower_64) / TWO_POW_64; + let mid_120_upper_56 = ((x_shifted_184 as u64) % TWO_POW_56) as Field; + let mid_120 = mid_120_lower_64 + TWO_POW_64 * mid_120_upper_56; - BigNum::from_be_bytes(x_bytes) -} + let x_shifted_240 = (x_shifted_184 - mid_120_upper_56) / (TWO_POW_56 as Field); -unconstrained fn __field_to_bignum_limbs(x: Field) -> [Field; 3] { - __field_to_bignum(x).limbs + let hi_120_lower_64 = (x_shifted_240 as u64) as Field; + // We don't need to go further, as we've reached 304 bits, and a Field is 254 bits. + let hi_120 = hi_120_lower_64; + + [low_120, mid_120, hi_120] } // Only works for bignums with modulus larger than the BN Fr size (which is true // for the bls12-381 Fr field). fn field_to_bignum(x: Field) -> F { - let __x_limbs = __field_to_bignum_limbs(x); + let __x_limbs = unsafe { __field_to_bignum_limbs(x) }; let mut check = __x_limbs[3 - 1]; for i in 1..3 { @@ -99,143 +86,37 @@ fn field_to_bignum(x: Field) -> F { BigNum { limbs: __x_limbs } } -// DANGER: this assumes the input bignum is <= the Noir field size. -// Only use this if you _know_ the data being passed in is small enough. -// -// Or actually, maybe it's not unsafe, if Field catches overflows? -fn unsafe_bignum_to_field(x: F) -> Field { - let mut result: Field = 0; - result += x.limbs[3 - 1]; - for i in 1..3 { - result *= LIMB_MAX; - result += x.limbs[3 - i - 1]; - } - result -} - -fn bignum_to_bytes(x: F) -> [u8] { - let limb_0_bytes: [u8; 15] = x.limbs[0].to_be_bytes(); - let limb_1_bytes: [u8; 15] = x.limbs[1].to_be_bytes(); - let limb_2_bytes: [u8; 2] = x.limbs[2].to_be_bytes(); - let mut out: [u8; 32] = [0; 32]; - for i in 0..32 { - out[i] = limb_0_bytes[i]; - out[i + 15] = limb_1_bytes[i]; - } - for i in 0..1 { - out[30 + i] = limb_2_bytes[i]; - } - std::static_assert(out.len() == 32, "bad byte decomposition of bignum"); - out -} - -// DANGER: this assumes the input bignum is <= the Noir field size. -// Only use this if you _know_ the data being passed in is small enough. -// -// This is inefficient, in the sense that we discard ~1 bit of blob space per -// 255-bit blob field, when converting it to a 245-bit noir field. Over the whole blob, -// we end up discarding 1 bit * 4096 fields_per_blob = 512 bytes = 16 words of data. -// BUT, it is much simpler to do this than to reconstitute 4096 disparate bits across -// the whole blob into 16 words. Perhaps the more complex approach should only be -// taken once aztec blobs are sufficiently full? -fn unsafe_blob_to_fields(blob: [F; FIELDS_PER_BLOB]) -> [Field; FIELDS_PER_BLOB] { - let mut blob_as_fields: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; +fn convert_blob_fields(blob_as_fields: [Field; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { + let mut blob: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; for i in 0..FIELDS_PER_BLOB { - blob_as_fields[i] = unsafe_bignum_to_field(blob[i]); - } - blob_as_fields -} - -unconstrained fn __unsafe_extract_top_bit(x: F) -> (Field, Field) { - let top_limb: Field = x.limbs[2]; - // The top_limb is at most 2 bytes (16 bits). - // 0x8000 = 2^15 = 32768 - let top_bit: Field = (top_limb as u16 / 0x8000) as Field; - let top_limb_with_top_bit_removed = top_limb - top_bit * 0x8000; - (top_bit, top_limb_with_top_bit_removed) -} - -// DANGER: it's named as "unsafe" because the caller MUST already have checked that -// each blob Field is formatted as (u1, Field). I.e. the "rhs" 254-bits should already -// fit within a Field. If the "rhs" 254 bits is larger than the field modulus, -// there will be an uncaught overflow of the 254-bits in the Field, resulting in -// an unintended tiny value. -// -// For efficiency, the top_bit is kept as a Field throughout. -fn unsafe_extract_top_bit(x: F) -> (Field, F) { - let (top_bit, top_limb_with_top_bit_removed) = __unsafe_extract_top_bit(x); - assert_eq(top_bit * 0x8000 + top_limb_with_top_bit_removed, x.limbs[2]); - - (top_bit, BigNum { limbs: [x.limbs[0], x.limbs[1], top_limb_with_top_bit_removed] }) -} - -// TODO(#8955): Use the below to tightly pack nr fields into bls fields? -// Not currently used because it adds a lot of complication to constructing/deconstructing blocks -fn blob_to_fields__tightly_packed(blob: [F; FIELDS_PER_BLOB]) -> [Field; NOIR_FIELDS_PER_BLOB] { - let mut blob_as_fields: [Field; NOIR_FIELDS_PER_BLOB] = [0; NOIR_FIELDS_PER_BLOB]; - let mut top_bits: [Field; FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB] = - [0; FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB]; - - // We start with [F; 4096]. - // The first 4064 of these bls-fields have a 255th bit (counting from 1) which can contribute towards - // new 254-bit noir fields. That is, we extract 4064 top-bits from the first 4064 of the 4096 bls-fields, - // and reconstitute them into 4064 / 254 = 16 extra noir fields. - // So we end up with 4096 + 16 = 4112 noir fields. - // Here we compute top_bits[0:4064] and blob_as_fields[0:4064]. - for i in 0..FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB { - let (top_bit, field_with_top_bit_removed): (Field, F) = unsafe_extract_top_bit(blob[i]); - top_bits[i] = top_bit; - blob_as_fields[i] = unsafe_bignum_to_field(field_with_top_bit_removed); - } - // Here we compute blob_as_fields[4064:4096]. - for i in FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB..FIELDS_PER_BLOB { - blob_as_fields[i] = unsafe_bignum_to_field(blob[i]); - } - // Here we compute blob_as_fields[4096:4112] from top_bits[0:4064] - for i in FIELDS_PER_BLOB..NOIR_FIELDS_PER_BLOB { - // the top_bits are assumed to be big-endian bit arrays: - let mut reconstituted_field = top_bits[0]; - for j in 1..254 { - let k = (i - FIELDS_PER_BLOB) * 254 + j; - reconstituted_field *= 2; - reconstituted_field += top_bits[k]; - // std::as_witness(reconstituted_field); // this was costing 4048 gates - } - blob_as_fields[i] = reconstituted_field; + blob[i] = field_to_bignum(blob_as_fields[i]); } - blob_as_fields + blob } -fn check_blob_sponge( - blob_as_fields: [Field; FIELDS_PER_BLOB], +pub fn check_block_blob_sponge( + blobs_as_fields: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], mut sponge_blob: SpongeBlob, -) -> ([F; FIELDS_PER_BLOB], Field) { - // Check that we haven't overfilled the blob (checking here as we need to check once per blob) - assert(sponge_blob.expected_fields <= FIELDS_PER_BLOB, "Attempted to overfill blob"); +) -> Field { + // Check that we haven't overfilled the blobs + assert( + sponge_blob.expected_fields <= FIELDS_PER_BLOB * BLOBS_PER_BLOCK, + "Attempted to overfill blobs", + ); // Check that the blob is full assert( sponge_blob.expected_fields == sponge_blob.fields, "Incorrect number of tx effects added to blob", ); - let txs_effects_hash = sponge_blob.squeeze(); - let hash = poseidon2_hash_subarray(blob_as_fields, sponge_blob.fields); - assert(hash == txs_effects_hash, "Mismatched hashed tx effects"); - let mut blob: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; - for i in 0..FIELDS_PER_BLOB { - blob[i] = field_to_bignum(blob_as_fields[i]); - // In fixed hash method, below check happens in above subarray hash - // should_check |= i == sponge_blob.fields; - // // check that if we have not filled the blob, the remaining values are indeed 0 - // // this ensures that we cannot add extra tx effects at the block-root stage from nowhere - // if should_check { - // assert(blob_as_fields[i] == 0, "Found non-0 tx effect beyond claimed length"); - // } - } - (blob, txs_effects_hash) + let sponge_hash = sponge_blob.squeeze(); + let hash = poseidon2_hash_subarray(blobs_as_fields, sponge_blob.fields); + assert(hash == sponge_hash, "Mismatched hashed tx effects"); + + sponge_hash } -fn compute_challenge(hashed_blob_fields: Field, kzg_commitment: [Field; 2]) -> Field { - let preimage = [hashed_blob_fields, kzg_commitment[0], kzg_commitment[1]]; +fn compute_challenge(hashed_blobs_fields: Field, kzg_commitment: BlobCommitment) -> Field { + let preimage = [hashed_blobs_fields, kzg_commitment.inner[0], kzg_commitment.inner[1]]; let challenge = std::hash::poseidon2::Poseidon2::hash(preimage, 3); challenge } @@ -247,14 +128,14 @@ fn compute_challenge(hashed_blob_fields: Field, kzg_commitment: [Field; 2]) -> F // we just need the bits of data. So we've simply encoded it as fitting inside a // [Field; 2], since two 254-bit fields more-than covers 381+1=382 bits. // See yarn-project/foundation/src/blob/index.ts -> commitmentToFields() for encoding -pub fn evaluate_blob( +fn evaluate_blob( blob_as_fields: [Field; FIELDS_PER_BLOB], - kzg_commitment: [Field; 2], - mut sponge_blob: SpongeBlob, + kzg_commitment: BlobCommitment, + hashed_blobs_fields: Field, ) -> BlobPublicInputs { - let (blob, txs_effects_hash) = check_blob_sponge(blob_as_fields, sponge_blob); - let challenge_z: Field = compute_challenge(txs_effects_hash, kzg_commitment); + let challenge_z: Field = compute_challenge(hashed_blobs_fields, kzg_commitment); let challenge_z_as_bignum: F = field_to_bignum(challenge_z); + let blob = convert_blob_fields(blob_as_fields); let y: F = barycentric_evaluate_blob_at_z(challenge_z_as_bignum, blob); // TODO(Miranda): Since we are verifying a root proof, the below doesn't apply. We should be hashing ALL root public inputs, including the blob ones. @@ -265,6 +146,32 @@ pub fn evaluate_blob( BlobPublicInputs { z: challenge_z, y, kzg_commitment } } +// Evaluates each blob required for a block +pub fn evaluate_blobs( + blobs_as_fields: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], + kzg_commitments: [BlobCommitment; BLOBS_PER_BLOCK], + mut sponge_blob: SpongeBlob, +) -> BlockBlobPublicInputs { + // Note that with multiple blobs per block, each blob uses the same hashed_blobs_fields in: + // challenge_z = H(hashed_blobs_fields, kzg_commitment[0], kzg_commitment[1]) + // This is ok, because each commitment is unique to the blob, and we need hashed_blobs_fields to encompass + // all fields in the blob, which it does. + let hashed_blobs_fields = check_block_blob_sponge(blobs_as_fields, sponge_blob); + let mut result = BlockBlobPublicInputs::empty(); + for i in 0..BLOBS_PER_BLOCK { + let single_blob_fields = array_splice(blobs_as_fields, i * FIELDS_PER_BLOB); + result.inner[i] = + evaluate_blob(single_blob_fields, kzg_commitments[i], hashed_blobs_fields); + if (result.inner[i].is_zero()) & (single_blob_fields[0] == 0) { + // We use empty PIs for empty blobs, to make it simpler to verify on L1. + // Since our fields come from the base rollup, we know they are tightly packed + // and should contain no 0 values among valid values => single_blob_fields[0] == 0. + result.inner[i] = BlobPublicInputs::empty(); + } + } + result +} + /** * ___d-1 * z^d - 1 \ omega^i @@ -287,6 +194,8 @@ pub fn evaluate_blob( * @return y = p(z) */ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { + // TODO(#9982): Delete below and go back to using config.nr - calculating ROOTS in unconstrained is insecure. + let ROOTS = unsafe { compute_roots_of_unity() }; // z ^ D: let mut t1 = z.__mul(z); @@ -498,204 +407,267 @@ fn barycentric_evaluate_blob_at_z(z: F, ys: [F; FIELDS_PER_BLOB]) -> F { y } -use dep::types::tests::fixture_builder::FixtureBuilder; - -// Helper to return (z^d - 1)/d (unsafe - test only) -fn z_d_helper(challenge_z: F) -> F { - let mut t1 = challenge_z.__mul(challenge_z); - let mut t2: F = BigNum::new(); - for _i in 0..LOG_FIELDS_PER_BLOB - 1 { - t2 = t1.__mul(t1); - t1 = t2; - } +mod tests { + // TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. + use crate::{ + blob::{ + barycentric_evaluate_blob_at_z, check_block_blob_sponge, evaluate_blob, evaluate_blobs, + field_to_bignum, + }, + blob_public_inputs::BlobCommitment, + unconstrained_config::{ + D, D_INV, F, FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB, LOG_FIELDS_PER_BLOB, + NOIR_FIELDS_PER_BLOB, + }, + }; + use bigint::{BigNum, fields::bls12_381Fr::BLS12_381_Fr_Params}; + use types::{ + abis::sponge_blob::SpongeBlob, + constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB}, + tests::{fixture_builder::FixtureBuilder, utils::pad_end}, + }; - let z_pow_d = t1; + // Helper to return (z^d - 1)/d (unsafe - test only) + fn z_d_helper(challenge_z: F) -> F { + let mut t1 = challenge_z.__mul(challenge_z); + let mut t2: F = BigNum::new(); + for _i in 0..LOG_FIELDS_PER_BLOB - 1 { + t2 = t1.__mul(t1); + t1 = t2; + } - let one: F = BigNum::one(); + let z_pow_d = t1; - t1 = z_pow_d.__sub(one); - let factor = t1.__mul(D_INV); - factor -} + let one: F = BigNum::one(); -#[test] -fn test_one_note() { - let mut tx_data = FixtureBuilder::new(); - tx_data.add_new_note_hash(1); - let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; - let blob_fields = tx_data.to_combined_accumulated_data().serialize(); - for i in 0..blob_fields.len() { - blob[i] = blob_fields[i]; + t1 = z_pow_d.__sub(one); + let factor = t1.__mul(D_INV); + factor } - let mut sponge_blob = SpongeBlob::new(blob_fields.len()); - sponge_blob.absorb(blob_fields, blob_fields.len()); - - let kzg_commitment_in = [1, 2]; // this is made-up nonsense. - let output = evaluate_blob(blob, kzg_commitment_in, sponge_blob); - let challenge_z = field_to_bignum(output.z); - let y = output.y; - // Our blob is all 0s, apart from one commitment of value 1 at position 0 - // It's in eval form => our barycentric formula to find p(z) becomes: - // - // z^d - 1 omega^0 z^d - 1 1 - // p(z) = --------- . note . --------- = --------- . 1 . --------- - // d z - omega^0 d z - 1 - // - // => - // We check that: - //* z^d - 1 - //* p(z).(z - 1) = --------- - //* d - // - let rhs = z_d_helper(challenge_z); - let z_minus_1 = challenge_z.__sub(BigNum::one()); - let lhs = y.__mul(z_minus_1); - assert_eq(lhs, rhs); -} -#[test] -fn test_base() { - let mut tx_data = FixtureBuilder::new(); - // Add some random bits of state - tx_data.append_note_hashes_with_logs(50); - tx_data.set_first_nullifier(); - tx_data.append_nullifiers(50); - tx_data.append_l2_to_l1_msgs(5); - tx_data.append_public_data_update_requests(5); - tx_data.append_unencrypted_log_hashes(5); - let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; - let blob_fields = tx_data.to_combined_accumulated_data().serialize(); - for i in 0..blob_fields.len() { - blob[i] = blob_fields[i]; + #[test] + unconstrained fn test_one_note() { + let mut tx_data = FixtureBuilder::new(); + tx_data.add_new_note_hash(1); + let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; + let blob_fields = tx_data.to_combined_accumulated_data().serialize(); + for i in 0..blob_fields.len() { + blob[i] = blob_fields[i]; + } + let mut sponge_blob = SpongeBlob::new(blob_fields.len()); + sponge_blob.absorb(blob_fields, blob_fields.len()); + + let kzg_commitment_in = BlobCommitment { inner: [1, 2] }; // this is made-up nonsense. + let padded_blob_fields = pad_end(blob, 0); + let hashed_blob = check_block_blob_sponge(padded_blob_fields, sponge_blob); + let output = evaluate_blob(blob, kzg_commitment_in, hashed_blob); + let challenge_z = field_to_bignum(output.z); + let y = output.y; + // Our blob is all 0s, apart from one commitment of value 1 at position 0 + // It's in eval form => our barycentric formula to find p(z) becomes: + // + // z^d - 1 omega^0 z^d - 1 1 + // p(z) = --------- . note . --------- = --------- . 1 . --------- + // d z - omega^0 d z - 1 + // + // => + // We check that: + //* z^d - 1 + //* p(z).(z - 1) = --------- + //* d + // + let rhs = z_d_helper(challenge_z); + let z_minus_1 = unsafe { challenge_z.__sub(BigNum::one()) }; + let lhs = y.__mul(z_minus_1); + assert_eq(lhs, rhs); } - let mut sponge_blob = SpongeBlob::new(blob_fields.len()); - sponge_blob.absorb(blob_fields, blob_fields.len()); - - let kzg_commitment_in = [1, 2]; // this is made-up nonsense. - let output = evaluate_blob(blob, kzg_commitment_in, sponge_blob); - let expected_z = std::hash::poseidon2::Poseidon2::hash( - [sponge_blob.squeeze(), kzg_commitment_in[0], kzg_commitment_in[1]], - 3, - ); - assert(expected_z == output.z); -} -// All hardcoded values in this test are taken from yarn-project/foundation/src/blob/blob.test.ts -> 'should evaluate a blob of 400 items' -#[test] -fn test_400() { - let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; - for i in 0..400 { - blob[i] = 3; + // TODO(Miranda): Uncomment this test when noir fix has been synced + // #[test] + // unconstrained fn test_base() { + // let mut tx_data = FixtureBuilder::new(); + // // Add some random bits of state + // tx_data.append_note_hashes_with_logs(50); + // tx_data.set_first_nullifier(); + // tx_data.append_nullifiers(50); + // tx_data.append_l2_to_l1_msgs(5); + // tx_data.append_public_data_update_requests(5); + // tx_data.append_unencrypted_log_hashes(5); + // let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; + // let blob_fields = tx_data.to_combined_accumulated_data().serialize(); + // for i in 0..blob_fields.len() { + // blob[i] = blob_fields[i]; + // } + // let mut sponge_blob = SpongeBlob::new(blob_fields.len()); + // sponge_blob.absorb(blob_fields, blob_fields.len()); + + // let kzg_commitment_in = [1, 2]; // this is made-up nonsense. + // let padded_blob_fields = pad_end(blob, 0); + // let hashed_blob = check_block_blob_sponge(padded_blob_fields, sponge_blob); + // let output = evaluate_blob(blob, kzg_commitment_in, hashed_blob); + // let expected_z = std::hash::poseidon2::Poseidon2::hash( + // [sponge_blob.squeeze(), kzg_commitment_in[0], kzg_commitment_in[1]], + // 3, + // ); + // assert(expected_z == output.z); + // } + + // All hardcoded values in this test are taken from yarn-project/foundation/src/blob/blob.test.ts -> 'should evaluate a blob of 400 items' + #[test] + unconstrained fn test_400() { + let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; + for i in 0..400 { + blob[i] = 3; + } + let mut sponge_blob = SpongeBlob::new(400); + sponge_blob.absorb(blob, 400); + + let kzg_commitment_in = BlobCommitment { + inner: [ + 0x00b2803d5fe972914ba3616033e2748bbaa6dbcddefc3721a54895a7a45e7750, + 0x0000000000000000000000000000004dd1a971c7e8d8292be943d05bccebcfea, + ], + }; + + let padded_blob_fields = pad_end(blob, 0); + let hashed_blob = check_block_blob_sponge(padded_blob_fields, sponge_blob); + let output = evaluate_blob(blob, kzg_commitment_in, hashed_blob); + + // y is a BLS field with value 0x212c4f0c0ee5e7dd037110686a4639d191dde7b57ab99b51e4b06e7d827b6c4c + let expected_y: F = BigNum { + limbs: [0xdde7b57ab99b51e4b06e7d827b6c4c, 0x4f0c0ee5e7dd037110686a4639d191, 0x212c], + }; + assert(expected_y == output.y); } - let mut sponge_blob = SpongeBlob::new(400); - sponge_blob.absorb(blob, 400); - let kzg_commitment_in = [ - 0x00b2803d5fe972914ba3616033e2748bbaa6dbcddefc3721a54895a7a45e7750, - 0x0000000000000000000000000000004dd1a971c7e8d8292be943d05bccebcfea, - ]; + // All hardcoded values in this test are taken from yarn-project/foundation/src/blob/blob.test.ts -> 'should evaluate full blobs' + #[test] + unconstrained fn test_full_blobs() { + let mut blob: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK] = + [0; FIELDS_PER_BLOB * BLOBS_PER_BLOCK]; + for j in 0..BLOBS_PER_BLOCK { + for i in 0..FIELDS_PER_BLOB { + blob[j * FIELDS_PER_BLOB + i] = i as Field + 2; + } + } - let output = evaluate_blob(blob, kzg_commitment_in, sponge_blob); + let mut sponge_blob = SpongeBlob::new(FIELDS_PER_BLOB * BLOBS_PER_BLOCK); + sponge_blob.absorb(blob, FIELDS_PER_BLOB * BLOBS_PER_BLOCK); - // y is a BLS field with value 0x212c4f0c0ee5e7dd037110686a4639d191dde7b57ab99b51e4b06e7d827b6c4c - let expected_y: F = BigNum { - limbs: [0xdde7b57ab99b51e4b06e7d827b6c4c, 0x4f0c0ee5e7dd037110686a4639d191, 0x212c], - }; - assert(expected_y == output.y); -} + let kzg_commitment_in = BlobCommitment { + inner: [ + 0x00ac771dea41e29fc2b7016c32731602c0812548ba0f491864a4e03fdb94b8d3, + 0x000000000000000000000000000000d195faad1967cdf005acf73088b0e8474a, + ], + }; -#[test(should_fail_with = "Found non-zero field after breakpoint")] -fn test_no_extra_blob_fields() { - let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; - // Fill fields with 50 inputs... - for i in 0..50 { - blob[i] = 3; + let output = evaluate_blobs(blob, [kzg_commitment_in; BLOBS_PER_BLOCK], sponge_blob); + + // y is a BLS field with value 0x52fd4e272015a79f3889cc9ab1d84bee4326de7d8ced52612ecc9ec137bd38ee + let expected_y: F = BigNum { + limbs: [0x26de7d8ced52612ecc9ec137bd38ee, 0x4e272015a79f3889cc9ab1d84bee43, 0x52fd], + }; + for j in 0..BLOBS_PER_BLOCK { + assert(expected_y == output.inner[j].y); + } } - // ...but the rollup's sponge is only expecting 45... - let mut sponge_blob = SpongeBlob::new(45); - sponge_blob.absorb(blob, 45); - let kzg_commitment_in = [1, 2]; // this is made-up nonsense. - // ...so the below should fail as it detects we are adding effects which did not come from the rollup. - let _ = evaluate_blob(blob, kzg_commitment_in, sponge_blob); -} + #[test(should_fail_with = "Found non-zero field after breakpoint")] + unconstrained fn test_no_extra_blob_fields() { + let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; + // Fill fields with 50 inputs... + for i in 0..50 { + blob[i] = 3; + } + // ...but the rollup's sponge is only expecting 45... + let mut sponge_blob = SpongeBlob::new(45); + sponge_blob.absorb(blob, 45); -#[test(should_fail_with = "Incorrect number of tx effects added to blob")] -fn test_absorbed_too_few_blob_fields() { - let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; - // Fill fields with 50 inputs... - for i in 0..50 { - blob[i] = 3; + // ...so the below should fail as it detects we are adding effects which did not come from the rollup. + let padded_blob_fields = pad_end(blob, 0); + let _ = check_block_blob_sponge(padded_blob_fields, sponge_blob); } - // ...but the rollup's sponge is expecting 100... - let mut sponge_blob = SpongeBlob::new(100); - sponge_blob.absorb(blob, 50); - let kzg_commitment_in = [1, 2]; // this is made-up nonsense. - // ...so the below should fail as it detects we have not added all the tx effects. - let _ = evaluate_blob(blob, kzg_commitment_in, sponge_blob); -} + #[test(should_fail_with = "Incorrect number of tx effects added to blob")] + unconstrained fn test_absorbed_too_few_blob_fields() { + let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; + // Fill fields with 50 inputs... + for i in 0..50 { + blob[i] = 3; + } + // ...but the rollup's sponge is expecting 100... + let mut sponge_blob = SpongeBlob::new(100); + sponge_blob.absorb(blob, 50); -#[test] -fn test_empty_blob() { - let mut blob: [Field; FIELDS_PER_BLOB] = [0; FIELDS_PER_BLOB]; - let mut sponge_blob = SpongeBlob::new(0); - // The below should not throw - let _ = check_blob_sponge(blob, sponge_blob); -} + // ...so the below should fail as it detects we have not added all the tx effects. + let padded_blob_fields = pad_end(blob, 0); + let _ = check_block_blob_sponge(padded_blob_fields, sponge_blob); + } -#[test] -fn test_barycentric() { - let z: F = BigNum { limbs: [2, 0, 0] }; + #[test] + unconstrained fn test_empty_blob() { + let mut blob: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK] = + [0; FIELDS_PER_BLOB * BLOBS_PER_BLOCK]; + let mut sponge_blob = SpongeBlob::new(0); + // The below should not throw + let _ = check_block_blob_sponge(blob, sponge_blob); + } - // many y's form a blob: - let mut ys: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; + #[test] + unconstrained fn test_barycentric() { + let z: F = BigNum { limbs: [2, 0, 0] }; - ys[0] = BigNum { limbs: [0x1234, 0, 0] }; - ys[1] = BigNum { limbs: [0xabcd, 0, 0] }; - ys[2] = BigNum { limbs: [0x69, 0, 0] }; + // many y's form a blob: + let mut ys: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; - // evaluate the blob at z = 2 to yield y: - let y = barycentric_evaluate_blob_at_z(z, ys); + ys[0] = BigNum { limbs: [0x1234, 0, 0] }; + ys[1] = BigNum { limbs: [0xabcd, 0, 0] }; + ys[2] = BigNum { limbs: [0x69, 0, 0] }; - let mut expected_y: [Field; 3] = [0; 3]; - if (FIELDS_PER_BLOB == 4096) { - // Computed with the eth consensus specs py lib - expected_y = [0x0c62e352a428e8e9842eadc1c106bd, 0x902c5b4968d755b6f49c0231e15af8, 0x00049a]; - // Also computed with cKzg, in the typescript tests: - // 0x049a902c5b4968d755b6f49c0231e15af80c62e352a428e8e9842eadc1c106bd - } - if (FIELDS_PER_BLOB == 8) { - // Computed with the eth consensus specs py lib (after hacking it to cope with blobs of size 8 instead of 4096): - expected_y = [0xb04cdea4304000053abffffffb203a, 0x0000000002e30785c8afa4496f8e38, 0x000000]; + // evaluate the blob at z = 2 to yield y: + let y = barycentric_evaluate_blob_at_z(z, ys); + + let mut expected_y: [Field; 3] = [0; 3]; + if (FIELDS_PER_BLOB == 4096) { + // Computed with the eth consensus specs py lib + expected_y = + [0x0c62e352a428e8e9842eadc1c106bd, 0x902c5b4968d755b6f49c0231e15af8, 0x00049a]; + // Also computed with cKzg, in the typescript tests: + // 0x049a902c5b4968d755b6f49c0231e15af80c62e352a428e8e9842eadc1c106bd + } + if (FIELDS_PER_BLOB == 8) { + // Computed with the eth consensus specs py lib (after hacking it to cope with blobs of size 8 instead of 4096): + expected_y = + [0xb04cdea4304000053abffffffb203a, 0x0000000002e30785c8afa4496f8e38, 0x000000]; + } + assert(y.limbs == expected_y); } - assert(y.limbs == expected_y); -} -// Helper function used to populate the hard-coded double_modulus value in the bls12381Fr.nr file in the bignum library. -unconstrained fn compute_double_modulus() -> [Field; 3] { - let two_p = [0x7b4805fffcb7fdfffffffe00000002, 0x4ea6533afa906673b0101343b00aa7, 0x00e7db]; - let NUM_LIMBS = 3; // must be >= 3 - let two_pow_120 = 2.pow_32(120); - let mut double_modulus: [Field; 3] = [0; 3]; + // Helper function used to populate the hard-coded double_modulus value in the bls12381Fr.nr file in the bignum library. + unconstrained fn compute_double_modulus() -> [Field; 3] { + let two_p = [0x7b4805fffcb7fdfffffffe00000002, 0x4ea6533afa906673b0101343b00aa7, 0x00e7db]; + let NUM_LIMBS = 3; // must be >= 3 + let two_pow_120 = 2.pow_32(120); + let mut double_modulus: [Field; 3] = [0; 3]; - double_modulus[0] = two_p[0] + two_pow_120; - for i in 1..NUM_LIMBS - 1 { - double_modulus[i] = two_p[i] + two_pow_120 - 1; + double_modulus[0] = two_p[0] + two_pow_120; + for i in 1..NUM_LIMBS - 1 { + double_modulus[i] = two_p[i] + two_pow_120 - 1; + } + double_modulus[NUM_LIMBS - 1] = two_p[NUM_LIMBS - 1] - 1; + double_modulus } - double_modulus[NUM_LIMBS - 1] = two_p[NUM_LIMBS - 1] - 1; - double_modulus -} -#[test] -unconstrained fn test_compute_double_modulus() { - let double_modulus = BLS12_381_Fr_Params::get_params().double_modulus; - assert_eq(double_modulus, compute_double_modulus()); -} + #[test] + unconstrained fn test_compute_double_modulus() { + let double_modulus = BLS12_381_Fr_Params::get_params().double_modulus; + assert_eq(double_modulus, compute_double_modulus()); + } -#[test] -unconstrained fn test_compute_d_inv() { - let d_inversed = D.__invmod(); - assert_eq(d_inversed, D_INV); + #[test] + unconstrained fn test_compute_d_inv() { + let d_inversed = D.__invmod(); + assert_eq(d_inversed, D_INV); + } } diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr index ef1a6d1dd8c..ce3c00068c6 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/blob_public_inputs.nr @@ -1,11 +1,35 @@ -use crate::config::F; +use crate::unconstrained_config::F; +// TODO(#9982): Replace unconstrained_config with config. use bigint::BigNum; -use types::{constants::BLOB_PUBLIC_INPUTS, traits::{Deserialize, Empty, Serialize}}; +use types::{ + constants::{BLOB_PUBLIC_INPUTS, BLOBS_PER_BLOCK}, + traits::{Deserialize, Empty, Serialize}, + utils::reader::Reader, +}; + +// NB: This only exists because a nested array of [[Field; 2]; N] did not build with earthly, but was fine otherwise +// For blobs, we use the compressed 48 byte BLS12 commitment to compute the challenge. We never need to operate on it, +// so it's encoded as 2 fields. The first is the first 31 bytes, and the second is the next 17 bytes. +pub struct BlobCommitment { + pub inner: [Field; 2], +} + +impl Eq for BlobCommitment { + fn eq(self, other: Self) -> bool { + self.inner.eq(other.inner) + } +} + +impl Empty for BlobCommitment { + fn empty() -> Self { + Self { inner: [0; 2] } + } +} pub struct BlobPublicInputs { - z: Field, - y: F, - kzg_commitment: [Field; 2], + pub z: Field, + pub y: F, + pub kzg_commitment: BlobCommitment, } impl BlobPublicInputs { @@ -15,11 +39,18 @@ impl BlobPublicInputs { // WARNING: unimplemented, below is nonsense to get noir to compile Self { z: self.z + other.z, y: self.y.add(other.y), kzg_commitment: self.kzg_commitment } } + + // This checks whether the blob public inputs represent data of all 0s + // This is not equivalent to being empty, since the challenge point z is a hash and won't have 0 value. + fn is_zero(self) -> bool { + // Note: there is no constrained is_zero in bignum + (self.y == BigNum { limbs: [0, 0, 0] }) & (self.kzg_commitment.inner == [0, 0]) + } } impl Empty for BlobPublicInputs { fn empty() -> Self { - Self { z: 0, y: BigNum::new(), kzg_commitment: [0; 2] } + Self { z: 0, y: BigNum::new(), kzg_commitment: BlobCommitment::empty() } } } @@ -30,8 +61,8 @@ impl Serialize for BlobPublicInputs { self.y.limbs[0], self.y.limbs[1], self.y.limbs[2], - self.kzg_commitment[0], - self.kzg_commitment[1], + self.kzg_commitment.inner[0], + self.kzg_commitment.inner[1], ] } } @@ -41,7 +72,7 @@ impl Deserialize for BlobPublicInputs { Self { z: fields[0], y: BigNum { limbs: [fields[1], fields[2], fields[3]] }, - kzg_commitment: [fields[4], fields[5]], + kzg_commitment: BlobCommitment { inner: [fields[4], fields[5]] }, } } } @@ -51,3 +82,53 @@ impl Eq for BlobPublicInputs { (self.z == other.z) & (self.y.eq(other.y)) & (self.kzg_commitment.eq(other.kzg_commitment)) } } + +// NB: it is much cleaner throughout the protocol circuits to define this struct rather than use a nested array. +// Once we accumulate blob inputs, it should be removed, and we just use BlobPublicInputs::accumulate everywhere. +pub struct BlockBlobPublicInputs { + pub inner: [BlobPublicInputs; BLOBS_PER_BLOCK], +} + +impl Empty for BlockBlobPublicInputs { + fn empty() -> Self { + Self { inner: [BlobPublicInputs::empty(); BLOBS_PER_BLOCK] } + } +} + +impl Serialize for BlockBlobPublicInputs { + fn serialize(self) -> [Field; BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK] { + let mut fields: BoundedVec = BoundedVec::new(); + for i in 0..BLOBS_PER_BLOCK { + fields.extend_from_array(self.inner[i].serialize()); + } + fields.storage() + } +} + +impl Deserialize for BlockBlobPublicInputs { + fn deserialize(fields: [Field; BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK]) -> Self { + let mut reader = Reader::new(fields); + let item = Self { + inner: reader.read_struct_array( + BlobPublicInputs::deserialize, + [BlobPublicInputs::empty(); BLOBS_PER_BLOCK], + ), + }; + reader.finish(); + item + } +} + +impl Eq for BlockBlobPublicInputs { + fn eq(self, other: Self) -> bool { + self.inner.eq(other.inner) + } +} + +#[test] +fn serialization_of_empty() { + let item = BlockBlobPublicInputs::empty(); + let serialized = item.serialize(); + let deserialized = BlockBlobPublicInputs::deserialize(serialized); + assert(item.eq(deserialized)); +} diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr index d156e6852ab..9fd051426c0 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/config.nr @@ -3,6 +3,8 @@ use types::constants::FIELDS_PER_BLOB; type F = BigNum<3, 255, BLS12_381_Fr_Params>; +// TODO(#9982): Delete unconstrained_config.nr and go back to using this file - calculating ROOTS in unconstrained is insecure. + global LOG_FIELDS_PER_BLOB: u32 = 12; global EXTRA_FIELDS_PER_BLOB: u32 = 16; // 16 = floor(4096 FIELDS_PER_BLOB / 254 noir_field_bits), wasting only 32 bits. global NOIR_FIELDS_PER_BLOB: u32 = FIELDS_PER_BLOB + EXTRA_FIELDS_PER_BLOB; diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr index f4be2c682e5..648f97948a9 100644 --- a/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/lib.nr @@ -1,3 +1,4 @@ mod blob_public_inputs; mod blob; -mod config; +mod unconstrained_config; +// TODO(#9982): Replace unconstrained_config with config and import ROOTS - calculating ROOTS in unconstrained is insecure. diff --git a/noir-projects/noir-protocol-circuits/crates/blob/src/unconstrained_config.nr b/noir-projects/noir-protocol-circuits/crates/blob/src/unconstrained_config.nr new file mode 100644 index 00000000000..34c2f6811ca --- /dev/null +++ b/noir-projects/noir-protocol-circuits/crates/blob/src/unconstrained_config.nr @@ -0,0 +1,106 @@ +use bigint::{BigNum, fields::bls12_381Fr::BLS12_381_Fr_Params}; +use types::constants::FIELDS_PER_BLOB; + +// TODO(#9982): Delete this file and go back to using config.nr - calculating ROOTS in unconstrained is insecure. + +type F = BigNum<3, 255, BLS12_381_Fr_Params>; + +global LOG_FIELDS_PER_BLOB: u32 = 12; +global EXTRA_FIELDS_PER_BLOB: u32 = 16; // 16 = floor(4096 FIELDS_PER_BLOB / 254 noir_field_bits), wasting only 32 bits. +global NOIR_FIELDS_PER_BLOB: u32 = FIELDS_PER_BLOB + EXTRA_FIELDS_PER_BLOB; +global FIELDS_CARRYING_AN_EXTRA_BIT_PER_BLOB: u32 = EXTRA_FIELDS_PER_BLOB * 254; // EXTRA_FIELDS_PER_BLOB * 254 = 4064. So the first 4064 bls Fr fields in the blob will carry an extra bit in their 255th bit position, that will be used to reconstitute 16 extra fields. +global D: F = BigNum { limbs: [4096, 0, 0] }; +global D_INV: F = + BigNum { limbs: [0x686828bfce5c19400fffff00100001, 0x6878b46ae3705eb6a46a89213de7d3, 0x73e6] }; + +unconstrained fn compute_level(idx_: u32) -> u32 { + // Count the number of trailing ones. + let mut count = 0; + let mut idx = idx_; + for _i in 0..LOG_FIELDS_PER_BLOB { + if (idx & 1 == 0) { + break; + } else { + count += 1; + idx >>= 1; + } + } + + count +} + +unconstrained fn compute_big_minus_arr( + _big_minus: u32, + _next_diff: u32, +) -> [u32; LOG_FIELDS_PER_BLOB - 2] { + let mut res: [u32; LOG_FIELDS_PER_BLOB - 2] = [0; LOG_FIELDS_PER_BLOB - 2]; + let mut big_minus = _big_minus; + let mut next_diff = _next_diff; + res[0] = big_minus; + for i in 1..LOG_FIELDS_PER_BLOB - 2 { + next_diff >>= 1; + big_minus += next_diff; + res[i] = big_minus; + } + assert(next_diff == 3); + res +} + +unconstrained fn bit_reversal_permutation(arr: [F; FIELDS_PER_BLOB]) -> [F; FIELDS_PER_BLOB] { + let mut arr_brp: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; + let PLUS = FIELDS_PER_BLOB >> 1; + let MINUS = PLUS >> 1; + let mut I = 0; + let mut next_diff = PLUS - (MINUS >> 1); + let mut big_minus = next_diff + MINUS; + + let big_minus_arr = compute_big_minus_arr(big_minus, next_diff); + + arr_brp[0] = arr[0]; + I += PLUS; + arr_brp[1] = arr[I]; + I -= MINUS; + arr_brp[2] = arr[I]; + I += PLUS; + arr_brp[3] = arr[I]; + + for i in 0..FIELDS_PER_BLOB / 4 - 1 { + let j = 4 * i + 4; + let level = compute_level(i); + I -= big_minus_arr[level]; + arr_brp[j] = arr[I]; + I += PLUS; + arr_brp[j + 1] = arr[I]; + I -= MINUS; + arr_brp[j + 2] = arr[I]; + I += PLUS; + arr_brp[j + 3] = arr[I]; + } + arr_brp +} + +// x ^ i for i in 0..4096 +unconstrained fn compute_powers(x: F) -> [F; FIELDS_PER_BLOB] { + let mut powers: [F; FIELDS_PER_BLOB] = [BigNum::new(); FIELDS_PER_BLOB]; + let mut current_power: F = BigNum::one(); + for i in 0..FIELDS_PER_BLOB { + powers[i] = current_power; + current_power = current_power.__mul(x); + } + powers +} + +pub unconstrained fn compute_roots_of_unity() -> [F; FIELDS_PER_BLOB] { + // The below const is found from: + // let order: F = BigNum { limbs: [ FIELDS_PER_BLOB, 0, 0 ]; + // let exp = BLS_MODULUS_SUB_1.udiv_mod(order); + // let exp: F = BigNum { limbs: [ 0x553bda402fffe5bfeffffffff00000, 0x3eda753299d7d483339d80809a1d80, 0x000007 ] }; // (MODULUS - 1) // 4096 + // let root_of_unity = PRIMITIVE_ROOT_OF_UNITY.__pow(exp); + let root_of_unity: F = BigNum { + limbs: [0xd1347b378fbf96e206da11a5d36306, 0x0a11a0f704f4fc3e8acfe0f8245f0a, 0x00564c], + }; + let mut roots_of_unity = compute_powers(root_of_unity); + bit_reversal_permutation(roots_of_unity) + // bit_reversal_permutation(&mut roots_of_unity); + // roots_of_unity +} diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr index db225e96feb..2035c9c4030 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/abis/block_root_or_block_merge_public_inputs.nr @@ -8,7 +8,7 @@ use dep::types::{ traits::{Deserialize, Empty, Serialize}, utils::reader::Reader, }; -use blob::blob_public_inputs::BlobPublicInputs; +use blob::blob_public_inputs::BlockBlobPublicInputs; pub struct FeeRecipient { recipient: EthAddress, @@ -54,7 +54,7 @@ pub struct BlockRootOrBlockMergePublicInputs { vk_tree_root: Field, // Root of allowed vk tree protocol_contract_tree_root: Field, // Root of protocol contract tree prover_id: Field, // TODO(#7346): Temporarily added prover_id while we verify block-root proofs on L1 - blob_public_inputs: [BlobPublicInputs; AZTEC_MAX_EPOCH_DURATION], // z, y, and C s.t. p(z) = y and C commits to p, for blob verification + blob_public_inputs: [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION], // z, y, and C s.t. p(z) = y and C commits to p, for blob verification } impl BlockRootOrBlockMergePublicInputs { @@ -77,7 +77,7 @@ impl Empty for BlockRootOrBlockMergePublicInputs { vk_tree_root: 0, protocol_contract_tree_root: 0, prover_id: 0, - blob_public_inputs: [BlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], + blob_public_inputs: [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], } } } @@ -147,8 +147,8 @@ impl Deserialize for BlockRootOr protocol_contract_tree_root: reader.read(), prover_id: reader.read(), blob_public_inputs: reader.read_struct_array( - BlobPublicInputs::deserialize, - [BlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], + BlockBlobPublicInputs::deserialize, + [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], ), }; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr index 085967eda3b..73da5991875 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/block_root_rollup_inputs.nr @@ -5,13 +5,13 @@ use crate::{ }, components, }; -use blob::{blob::evaluate_blob, blob_public_inputs::BlobPublicInputs}; +use blob::{blob::evaluate_blobs, blob_public_inputs::{BlobCommitment, BlockBlobPublicInputs}}; use parity_lib::root::root_rollup_parity_input::RootRollupParityInput; use types::{ abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot, constants::{ - ARCHIVE_HEIGHT, AZTEC_MAX_EPOCH_DURATION, FIELDS_PER_BLOB, L1_TO_L2_MSG_SUBTREE_HEIGHT, - L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, MERGE_ROLLUP_INDEX, + ARCHIVE_HEIGHT, AZTEC_MAX_EPOCH_DURATION, BLOBS_PER_BLOCK, FIELDS_PER_BLOB, + L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, MERGE_ROLLUP_INDEX, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PRIVATE_BASE_ROLLUP_VK_INDEX, PUBLIC_BASE_ROLLUP_VK_INDEX, }, @@ -49,13 +49,12 @@ pub struct BlockRootRollupInputs { prover_id: Field, // Fields for blob verification made of all tx effects in this block // (will likely change to be accumulated and sent up to the final root) - // TODO(Miranda): Temporarily working with one blob to ensure things run - blob_fields: [Field; FIELDS_PER_BLOB], - // see blob/src/main.nr -> main() - this is used for creating the challenge z - blob_commitment: [Field; 2], - // The EVM blob hash, can be injected here as the contract check its validity vs the blob_public_inputs below - // NB: to fit it into a field, we remove the first byte denoting the VERSIONED_HASH_VERSION_KZG - blob_hash: Field, + blobs_fields: [Field; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], + // see blob/src/main.nr -> main() - these are used for creating the challenge z + blob_commitments: [BlobCommitment; BLOBS_PER_BLOCK], + // Flat sha256 hash of the EVM blob hashes, can be injected here as the contract check its validity vs the blob_public_inputs below + // NB: to fit it into a field, we truncate to 31 bytes + blobs_hash: Field, } impl BlockRootRollupInputs { @@ -100,7 +99,7 @@ impl BlockRootRollupInputs { let content_commitment = ContentCommitment { num_txs: (left.num_txs + right.num_txs) as Field, - blob_hash: self.blob_hash, + blobs_hash: self.blobs_hash, in_hash: self.l1_to_l2_roots.public_inputs.sha_root, out_hash: components::compute_out_hash(self.previous_rollup_data), }; @@ -131,10 +130,10 @@ impl BlockRootRollupInputs { fee_arr[0] = FeeRecipient { recipient: left.constants.global_variables.coinbase, value: total_fees }; - let mut blob_public_inputs = [BlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION]; - blob_public_inputs[0] = evaluate_blob( - self.blob_fields, - self.blob_commitment, + let mut blob_public_inputs = [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION]; + blob_public_inputs[0] = evaluate_blobs( + self.blobs_fields, + self.blob_commitments, right.end_sponge_blob, ); @@ -167,9 +166,9 @@ impl Empty for BlockRootRollupInputs { new_archive_sibling_path: [0; ARCHIVE_HEIGHT], previous_block_hash: 0, prover_id: 0, - blob_fields: [0; FIELDS_PER_BLOB], - blob_commitment: [0; 2], - blob_hash: 0, + blobs_fields: [0; FIELDS_PER_BLOB * BLOBS_PER_BLOCK], + blob_commitments: [BlobCommitment::empty(); BLOBS_PER_BLOCK], + blobs_hash: 0, } } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr index 4e8f92463d1..6c7223dab66 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/empty_block_root_rollup_inputs.nr @@ -1,7 +1,7 @@ use crate::abis::block_root_or_block_merge_public_inputs::{ BlockRootOrBlockMergePublicInputs, FeeRecipient, }; -use blob::blob_public_inputs::BlobPublicInputs; +use blob::blob_public_inputs::BlockBlobPublicInputs; use types::abis::{ append_only_tree_snapshot::AppendOnlyTreeSnapshot, global_variables::GlobalVariables, }; @@ -31,7 +31,7 @@ impl EmptyBlockRootRollupInputs { vk_tree_root: self.vk_tree_root, protocol_contract_tree_root: self.protocol_contract_tree_root, prover_id: self.prover_id, - blob_public_inputs: [BlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], + blob_public_inputs: [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION], } } } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr index 5ac8a758ad3..f9c527cf425 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/block_root/mod.nr @@ -42,7 +42,7 @@ mod tests { } #[test] - fn check_blob() { + unconstrained fn check_blob() { let inputs = default_block_root_rollup_inputs(); let outputs = inputs.block_root_rollup_circuit(); @@ -56,15 +56,19 @@ mod tests { let hashed_tx_effects = expected_sponge.squeeze(); let expected_z = Poseidon2::hash( - [hashed_tx_effects, inputs.blob_commitment[0], inputs.blob_commitment[1]], + [ + hashed_tx_effects, + inputs.blob_commitments[0].inner[0], + inputs.blob_commitments[0].inner[1], + ], 3, ); - assert(outputs.blob_public_inputs[0].z == expected_z); + assert(outputs.blob_public_inputs[0].inner[0].z == expected_z); } #[test(should_fail_with = "block's first blob sponge was not empty")] - fn check_blob_empty() { + unconstrained fn check_blob_empty() { let mut inputs = default_block_root_rollup_inputs(); inputs.previous_rollup_data[0].base_or_merge_rollup_public_inputs.start_sponge_blob.fields = 1; diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr index 7f8f3ad9ed3..9fb87848685 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/components.nr @@ -27,7 +27,7 @@ use dep::types::{ traits::is_empty, utils::{arrays::{array_concat, array_length, array_merge}, field::field_from_bytes}, }; -use blob::blob_public_inputs::BlobPublicInputs; +use blob::blob_public_inputs::BlockBlobPublicInputs; /** * Asserts that the tree formed by rollup circuits is filled greedily from L to R @@ -170,7 +170,7 @@ pub fn accumulate_blocks_fees( pub fn accumulate_blob_public_inputs( left: BlockRootOrBlockMergePublicInputs, right: BlockRootOrBlockMergePublicInputs, -) -> [BlobPublicInputs; AZTEC_MAX_EPOCH_DURATION] { +) -> [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION] { let left_len = array_length(left.blob_public_inputs); let right_len = array_length(right.blob_public_inputs); assert( @@ -179,7 +179,7 @@ pub fn accumulate_blob_public_inputs( ); // NB: For some reason, the below is around 150k gates cheaper than array_merge let mut add_from_left = true; - let mut result = [BlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION]; + let mut result = [BlockBlobPublicInputs::empty(); AZTEC_MAX_EPOCH_DURATION]; for i in 0..result.len() { add_from_left &= i != left_len; if (add_from_left) { @@ -330,7 +330,6 @@ pub fn append_tx_effects_for_blob( // NB: The array_length function does NOT constrain we have a sorted left-packed array. // We can use it because all inputs here come from the kernels which DO contrain left-packing. // If that ever changes, we will have to constrain it by counting items differently. - // NOTE HASHES array_len = array_length(note_hashes); if array_len != 0 { diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr index 67e2b1ad433..a54ce7c1e3e 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/root/root_rollup_public_inputs.nr @@ -1,7 +1,7 @@ use crate::abis::block_root_or_block_merge_public_inputs::FeeRecipient; use dep::types::abis::append_only_tree_snapshot::AppendOnlyTreeSnapshot; use dep::types::constants::AZTEC_MAX_EPOCH_DURATION; -use blob::blob_public_inputs::BlobPublicInputs; +use blob::blob_public_inputs::BlockBlobPublicInputs; pub struct RootRollupPublicInputs { // Snapshot of archive tree before/after this rollup has been processed previous_archive: AppendOnlyTreeSnapshot, @@ -15,5 +15,5 @@ pub struct RootRollupPublicInputs { vk_tree_root: Field, protocol_contract_tree_root: Field, prover_id: Field, - blob_public_inputs: [BlobPublicInputs; AZTEC_MAX_EPOCH_DURATION], + blob_public_inputs: [BlockBlobPublicInputs; AZTEC_MAX_EPOCH_DURATION], } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/block_root_rollup_inputs.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/block_root_rollup_inputs.nr index a96a8f5ff5e..556d308b3f3 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/block_root_rollup_inputs.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/block_root_rollup_inputs.nr @@ -58,8 +58,8 @@ pub fn default_block_root_rollup_inputs() -> BlockRootRollupInputs { inputs.previous_rollup_data = default_previous_rollup_data(); - inputs.blob_fields[0] = 1; - inputs.blob_fields[1] = 2; + inputs.blobs_fields[0] = 1; + inputs.blobs_fields[1] = 2; inputs } diff --git a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr index bcb54ad5345..714c410eef9 100644 --- a/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr +++ b/noir-projects/noir-protocol-circuits/crates/rollup-lib/src/tests/previous_rollup_block_data.nr @@ -55,8 +55,10 @@ pub fn default_previous_rollup_block_data() -> [PreviousRollupBlockData; 2] { previous_rollup_data[0].block_root_or_block_merge_public_inputs.fees[0].value = 10; previous_rollup_data[1].block_root_or_block_merge_public_inputs.fees[0].value = 15; - previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs[0].z = 1; - previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs[0].z = 2; + previous_rollup_data[0].block_root_or_block_merge_public_inputs.blob_public_inputs[0].inner[0].z = + 1; + previous_rollup_data[1].block_root_or_block_merge_public_inputs.blob_public_inputs[0].inner[0].z = + 2; previous_rollup_data } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/abis/sponge_blob.nr b/noir-projects/noir-protocol-circuits/crates/types/src/abis/sponge_blob.nr index dc77b46ec37..fc65d14e083 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/abis/sponge_blob.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/abis/sponge_blob.nr @@ -1,5 +1,5 @@ use crate::{ - constants::{FIELDS_PER_BLOB, SPONGE_BLOB_LENGTH}, + constants::{BLOBS_PER_BLOCK, FIELDS_PER_BLOB, SPONGE_BLOB_LENGTH}, hash::poseidon2_absorb_chunks_existing_sponge, traits::{Deserialize, Empty, Serialize}, }; @@ -19,16 +19,16 @@ use std::hash::poseidon2::Poseidon2; // The hash is used as part of the blob challenge, as we've proven it encompasses all elts of the blob. // Init is given by input len * 2^64 (see noir/noir-repo/noir_stdlib/src/hash/poseidon2.nr -> hash_internal) -global IV: Field = (FIELDS_PER_BLOB as Field) * 18446744073709551616; +global IV: Field = (FIELDS_PER_BLOB * BLOBS_PER_BLOCK) as Field * 18446744073709551616; pub struct SpongeBlob { - sponge: Poseidon2, - fields: u32, - expected_fields: u32, // The hinted number of tx effects this will absorb + pub sponge: Poseidon2, + pub fields: u32, + pub expected_fields: u32, // The hinted number of tx effects this will absorb } impl SpongeBlob { - pub fn new_full_blob() -> Self { + pub fn new_full_blobs() -> Self { Self { sponge: Poseidon2::new(IV), fields: 0, expected_fields: 0 } } 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 12b3cfc9017..2c5068c520e 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/constants.nr @@ -136,6 +136,7 @@ pub global FUNCTION_SELECTOR_NUM_BYTES: Field = 4; pub global INITIALIZATION_SLOT_SEPARATOR: Field = 1000_000_000; pub global INITIAL_L2_BLOCK_NUM: Field = 1; pub global FIELDS_PER_BLOB: u32 = 4096; +pub global BLOBS_PER_BLOCK: u32 = 3; pub global PRIVATE_LOG_SIZE_IN_BYTES: u32 = 576; // This is currently defined by aztec-nr/aztec/src/encrypted_logs/payload.nr. See the comment there for how this value is calculated. pub global AZTEC_MAX_EPOCH_DURATION: u32 = 32; // The following is taken from building a block and looking at the `lastArchive` value in it. @@ -515,12 +516,12 @@ pub global BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH: u32 = 2 + 1 /* vk_tree_root */ + 1 /* protocol_contract_tree_root */ + 1 /* prover_id */ - + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS; + + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK; // + 8 for previous_block_hash, end_block_hash, end_timestamp, end_block_number, out_hash, vk_tree_root, protocol_contract_tree_root, prover_id pub global ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH: u32 = 2 * APPEND_ONLY_TREE_SNAPSHOT_LENGTH + 8 + AZTEC_MAX_EPOCH_DURATION * FEE_RECIPIENT_LENGTH - + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS; + + AZTEC_MAX_EPOCH_DURATION * BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK; pub global GET_NOTES_ORACLE_RETURN_LENGTH: u32 = 674; pub global NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NOTE_HASHES_PER_TX; pub global NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP: u32 = 32 * MAX_NULLIFIERS_PER_TX; diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr index 53600207421..05948539625 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/content_commitment.nr @@ -2,7 +2,7 @@ use crate::{constants::CONTENT_COMMITMENT_LENGTH, traits::{Deserialize, Empty, S pub struct ContentCommitment { num_txs: Field, - blob_hash: Field, + blobs_hash: Field, in_hash: Field, out_hash: Field, } @@ -12,7 +12,7 @@ impl Serialize for ContentCommitment { let mut fields: BoundedVec = BoundedVec::new(); fields.push(self.num_txs); - fields.push(self.blob_hash); + fields.push(self.blobs_hash); fields.push(self.in_hash); fields.push(self.out_hash); @@ -24,26 +24,26 @@ impl Deserialize for ContentCommitment { fn deserialize(serialized: [Field; CONTENT_COMMITMENT_LENGTH]) -> Self { let num_txs = serialized[0]; - let blob_hash = serialized[1]; + let blobs_hash = serialized[1]; let in_hash = serialized[2]; let out_hash = serialized[3]; - Self { num_txs, blob_hash, in_hash, out_hash } + Self { num_txs, blobs_hash, in_hash, out_hash } } } impl Empty for ContentCommitment { fn empty() -> Self { - Self { num_txs: 0, blob_hash: 0, in_hash: 0, out_hash: 0 } + Self { num_txs: 0, blobs_hash: 0, in_hash: 0, out_hash: 0 } } } impl Eq for ContentCommitment { fn eq(self, other: Self) -> bool { (self.num_txs == other.num_txs) - & (self.blob_hash == other.blob_hash) + & (self.blobs_hash == other.blobs_hash) & (self.in_hash == other.in_hash) & (self.out_hash == other.out_hash) } diff --git a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr index fdd6a184b54..4c85197447a 100644 --- a/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr +++ b/noir-projects/noir-protocol-circuits/crates/types/src/utils/arrays.nr @@ -142,6 +142,19 @@ where result } +// Helper fn to create a subarray from a given array +pub fn array_splice(array: [T; N], offset: u32) -> [T; M] +where + T: Empty, +{ + assert(M + offset <= N, "Subarray length larger than array length"); + let mut result: [T; M] = [T::empty(); M]; + for i in 0..M { + result[i] = array[offset + i]; + } + result +} + pub fn check_permutation( original_array: [T; N], permuted_array: [T; N], diff --git a/yarn-project/archiver/src/archiver/archiver.test.ts b/yarn-project/archiver/src/archiver/archiver.test.ts index 95f6a8899a6..84491acd13c 100644 --- a/yarn-project/archiver/src/archiver/archiver.test.ts +++ b/yarn-project/archiver/src/archiver/archiver.test.ts @@ -452,7 +452,7 @@ function makeMessageSentEventWithIndexInL2BlockSubtree( function makeRollupTx(l2Block: L2Block) { const header = toHex(l2Block.header.toBuffer()); const body = toHex(l2Block.body.toBuffer()); - const blobInput = new Blob(l2Block.body.toBlobFields()).getEthBlobEvaluationInputs(); + const blobInput = Blob.getEthBlobEvaluationInputs(Blob.getBlobs(l2Block.body.toBlobFields())); const archive = toHex(l2Block.archive.root.toBuffer()); const blockHash = toHex(l2Block.header.hash().toBuffer()); const input = encodeFunctionData({ diff --git a/yarn-project/archiver/src/archiver/data_retrieval.ts b/yarn-project/archiver/src/archiver/data_retrieval.ts index 6d912609183..f477fc20a15 100644 --- a/yarn-project/archiver/src/archiver/data_retrieval.ts +++ b/yarn-project/archiver/src/archiver/data_retrieval.ts @@ -175,12 +175,14 @@ async function getBlockFromRollupTx( } // TODO(#9101): Once we stop publishing calldata, we will still need the blobCheck below to ensure that the block we are building does correspond to the blob fields - const blobCheck = new Blob(blockFields); - if (blobCheck.getEthBlobEvaluationInputs() !== blobInputs) { + const blobCheck = Blob.getBlobs(blockFields); + if (Blob.getEthBlobEvaluationInputs(blobCheck) !== blobInputs) { // NB: We can just check the blobhash here, which is the first 32 bytes of blobInputs // A mismatch means that the fields published in the blob in propose() do NOT match those in the extracted block. throw new Error( - `Block body mismatched with blob for block number ${l2BlockNum}. \nExpected: ${blobCheck.getEthBlobEvaluationInputs()} \nGot: ${blobInputs}`, + `Block body mismatched with blob for block number ${l2BlockNum}. \nExpected: ${Blob.getEthBlobEvaluationInputs( + blobCheck, + )} \nGot: ${blobInputs}`, ); } @@ -291,7 +293,7 @@ export async function retrieveL2ProofsFromRollup( export type SubmitBlockProof = { archiveRoot: Fr; proverId: Fr; - aggregationObject: Buffer; + blobPublicInputsAndAggregationObject: Buffer; proof: Proof; }; @@ -314,12 +316,12 @@ export async function getProofFromSubmitProofTx( let proverId: Fr; let archiveRoot: Fr; - let aggregationObject: Buffer; + let blobPublicInputsAndAggregationObject: Buffer; let proof: Proof; if (functionName === 'submitEpochRootProof') { const [_epochSize, nestedArgs, _fees, aggregationObjectHex, proofHex] = args!; - aggregationObject = Buffer.from(hexToBytes(aggregationObjectHex)); + blobPublicInputsAndAggregationObject = Buffer.from(hexToBytes(aggregationObjectHex)); proverId = Fr.fromString(nestedArgs[6]); archiveRoot = Fr.fromString(nestedArgs[1]); proof = Proof.fromBuffer(Buffer.from(hexToBytes(proofHex))); @@ -333,7 +335,7 @@ export async function getProofFromSubmitProofTx( return { proverId, - aggregationObject, + blobPublicInputsAndAggregationObject, archiveRoot, proof, }; diff --git a/yarn-project/circuit-types/src/body.ts b/yarn-project/circuit-types/src/body.ts index 981b9f7ddeb..27c612f02ac 100644 --- a/yarn-project/circuit-types/src/body.ts +++ b/yarn-project/circuit-types/src/body.ts @@ -1,4 +1,6 @@ import { type Fr } from '@aztec/circuits.js'; +import { Blob } from '@aztec/foundation/blob'; +import { sha256Trunc } from '@aztec/foundation/crypto'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; import { inspect } from 'util'; @@ -105,6 +107,17 @@ export class Body { }`; } + /** + * Computes the blobsHash as used in the header. + * This hash is also computed in the Rollup contract. + * @returns The blobs hash. + */ + getBlobsHash() { + const blobs = Blob.getBlobs(this.toBlobFields()); + const blobHashesBuffer = serializeToBuffer(blobs.map(b => b.getEthVersionedBlobHash())); + return sha256Trunc(blobHashesBuffer); + } + get noteEncryptedLogs(): EncryptedNoteL2BlockL2Logs { const logs = this.txEffects.map(txEffect => txEffect.noteEncryptedLogs); diff --git a/yarn-project/circuits.js/src/constants.gen.ts b/yarn-project/circuits.js/src/constants.gen.ts index fc3192b0d61..c00adfa1aa2 100644 --- a/yarn-project/circuits.js/src/constants.gen.ts +++ b/yarn-project/circuits.js/src/constants.gen.ts @@ -82,6 +82,7 @@ export const FUNCTION_SELECTOR_NUM_BYTES = 4; export const INITIALIZATION_SLOT_SEPARATOR = 1000000000; export const INITIAL_L2_BLOCK_NUM = 1; export const FIELDS_PER_BLOB = 4096; +export const BLOBS_PER_BLOCK = 3; export const PRIVATE_LOG_SIZE_IN_BYTES = 576; export const AZTEC_MAX_EPOCH_DURATION = 32; export const GENESIS_ARCHIVE_ROOT = 19007378675971183768036762391356802220352606103602592933942074152320327194720n; @@ -216,8 +217,8 @@ export const KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 605; export const AVM_CIRCUIT_PUBLIC_INPUTS_LENGTH = 1006; export const CONSTANT_ROLLUP_DATA_LENGTH = 13; export const BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 51; -export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 282; -export const ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 268; +export const BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 666; +export const ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 652; export const GET_NOTES_ORACLE_RETURN_LENGTH = 674; export const NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048; export const NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048; diff --git a/yarn-project/circuits.js/src/structs/blob_public_inputs.test.ts b/yarn-project/circuits.js/src/structs/blob_public_inputs.test.ts index 9cd802b8d6b..9dc9c42d7be 100644 --- a/yarn-project/circuits.js/src/structs/blob_public_inputs.test.ts +++ b/yarn-project/circuits.js/src/structs/blob_public_inputs.test.ts @@ -1,9 +1,9 @@ import { Blob } from '@aztec/foundation/blob'; import { randomInt } from '@aztec/foundation/crypto'; -import { BLOB_PUBLIC_INPUTS } from '../constants.gen.js'; -import { makeBlobPublicInputs } from '../tests/factories.js'; -import { BlobPublicInputs } from './blob_public_inputs.js'; +import { BLOBS_PER_BLOCK, BLOB_PUBLIC_INPUTS } from '../constants.gen.js'; +import { makeBlobPublicInputs, makeBlockBlobPublicInputs } from '../tests/factories.js'; +import { BlobPublicInputs, BlockBlobPublicInputs } from './blob_public_inputs.js'; import { Fr } from './index.js'; describe('BlobPublicInputs', () => { @@ -40,3 +40,40 @@ describe('BlobPublicInputs', () => { expect(fields.length).toBe(BLOB_PUBLIC_INPUTS); }); }); + +describe('BlockBlobPublicInputs', () => { + let blobPI: BlockBlobPublicInputs; + + beforeAll(() => { + blobPI = makeBlockBlobPublicInputs(randomInt(1000)); + }); + + it('serializes to buffer and deserializes it back', () => { + const buffer = blobPI.toBuffer(); + const res = BlockBlobPublicInputs.fromBuffer(buffer); + expect(res).toEqual(blobPI); + }); + + it('converts correctly from Blob class', () => { + const blobs = Array.from({ length: BLOBS_PER_BLOCK }, (_, i) => new Blob(Array(400).fill(new Fr(i + 1)))); + const converted = BlockBlobPublicInputs.fromBlobs(blobs); + converted.inner.forEach((blobPI, i) => { + expect(blobPI.z).toEqual(blobs[i].challengeZ); + expect(Buffer.from(blobPI.y.toString(16), 'hex')).toEqual(blobs[i].evaluationY); + expect(blobPI.kzgCommitment).toEqual(blobs[i].commitmentToFields()); + expect(blobPI.commitmentToBuffer()).toEqual(blobs[i].commitment); + }); + }); + + it('serializes to field array and deserializes it back', () => { + const fieldArray = blobPI.toFields(); + const res = BlockBlobPublicInputs.fromFields(fieldArray); + expect(res).toEqual(blobPI); + }); + + // NB: In noir, blob.y is represented as a BigNum = 3x Fr fields. In ts, we use bigint for ease of calcs. + it('number of fields matches constant', () => { + const fields = blobPI.toFields(); + expect(fields.length).toBe(BLOB_PUBLIC_INPUTS * BLOBS_PER_BLOCK); + }); +}); diff --git a/yarn-project/circuits.js/src/structs/blob_public_inputs.ts b/yarn-project/circuits.js/src/structs/blob_public_inputs.ts index 66d6238c273..098ebbd11f0 100644 --- a/yarn-project/circuits.js/src/structs/blob_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/blob_public_inputs.ts @@ -1,9 +1,13 @@ -import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer'; -import { type Blob } from '@aztec/foundation/blob'; +import { makeTuple } from '@aztec/foundation/array'; +import { toBigIntBE, toBufferBE, toHex } from '@aztec/foundation/bigint-buffer'; +import { Blob } from '@aztec/foundation/blob'; +import { sha256Trunc } from '@aztec/foundation/crypto'; import { Fr } from '@aztec/foundation/fields'; import { BufferReader, FieldReader, type Tuple, serializeToBuffer } from '@aztec/foundation/serialize'; import { type FieldsOf } from '@aztec/foundation/types'; +import { BLOBS_PER_BLOCK } from '../constants.gen.js'; + /** * Public inputs required to be passed from our rollup circuits to verify a blob. */ @@ -21,6 +25,10 @@ export class BlobPublicInputs { return new BlobPublicInputs(Fr.ZERO, 0n, [Fr.ZERO, Fr.ZERO]); } + isEmpty(): boolean { + return this.z.isZero() && this.y == 0n && this.kzgCommitment[0].isZero() && this.kzgCommitment[1].isZero(); + } + static fromBuffer(buffer: Buffer | BufferReader): BlobPublicInputs { const reader = BufferReader.asReader(buffer); return new BlobPublicInputs(Fr.fromBuffer(reader), toBigIntBE(reader.readBytes(32)), reader.readArray(2, Fr)); @@ -79,3 +87,67 @@ export class BlobPublicInputs { ); } } + +// NB: it is much cleaner throughout the protocol circuits to define this struct rather than use a nested array. +// Once we accumulate blob inputs, it should be removed, and we just use BlobPublicInputs::accumulate everywhere. +export class BlockBlobPublicInputs { + constructor(public inner: Tuple) {} + + static empty(): BlockBlobPublicInputs { + return new BlockBlobPublicInputs(makeTuple(BLOBS_PER_BLOCK, BlobPublicInputs.empty)); + } + + static fromBuffer(buffer: Buffer | BufferReader): BlockBlobPublicInputs { + const reader = BufferReader.asReader(buffer); + return new BlockBlobPublicInputs(reader.readArray(BLOBS_PER_BLOCK, BlobPublicInputs)); + } + + toBuffer() { + return serializeToBuffer(...BlockBlobPublicInputs.getFields(this)); + } + + static fromFields(fields: Fr[] | FieldReader): BlockBlobPublicInputs { + const reader = FieldReader.asReader(fields); + return new BlockBlobPublicInputs(reader.readArray(BLOBS_PER_BLOCK, BlobPublicInputs)); + } + + toFields() { + return this.inner.map(i => i.toFields()).flat(); + } + + static getFields(fields: FieldsOf) { + return [fields.inner] as const; + } + + static fromBlobs(inputs: Blob[]): BlockBlobPublicInputs { + const inner = makeTuple(BLOBS_PER_BLOCK, BlobPublicInputs.empty); + if (inputs.length > BLOBS_PER_BLOCK) { + throw new Error(`Can only fit ${BLOBS_PER_BLOCK} in one BlockBlobPublicInputs instance (given ${inputs.length})`); + } + inputs.forEach((input, i) => { + inner[i] = BlobPublicInputs.fromBlob(input); + }); + return new BlockBlobPublicInputs(inner); + } + + getBlobsHash() { + const blobHashes = this.inner.map(item => + item.isEmpty() ? Buffer.alloc(0) : Blob.getEthVersionedBlobHash(item.commitmentToBuffer()), + ); + return sha256Trunc(serializeToBuffer(blobHashes)); + } + + // The below is used to send to L1 for proof verification + toString() { + const nonEmptyBlobs = this.inner.filter(item => !item.isEmpty()); + // Write the number of blobs for L1 to verify + let buf = Buffer.alloc(1); + buf.writeUInt8(nonEmptyBlobs.length); + // Using standard toBuffer() does not correctly encode the commitment + // On L1, it's a 48 byte number, which we convert to 2 fields for use in the circuits + nonEmptyBlobs.forEach(blob => { + buf = Buffer.concat([buf, blob.z.toBuffer(), toBufferBE(blob.y, 32), blob.commitmentToBuffer()]); + }); + return buf.toString('hex'); + } +} diff --git a/yarn-project/circuits.js/src/structs/content_commitment.ts b/yarn-project/circuits.js/src/structs/content_commitment.ts index 52b3f79bad8..2eb8846ec60 100644 --- a/yarn-project/circuits.js/src/structs/content_commitment.ts +++ b/yarn-project/circuits.js/src/structs/content_commitment.ts @@ -9,12 +9,12 @@ import { CONTENT_COMMITMENT_LENGTH } from '../constants.gen.js'; export const NUM_BYTES_PER_SHA256 = 32; export class ContentCommitment { - constructor(public numTxs: Fr, public blobHash: Buffer, public inHash: Buffer, public outHash: Buffer) { + constructor(public numTxs: Fr, public blobsHash: Buffer, public inHash: Buffer, public outHash: Buffer) { // NB: we do not calculate blobHash in the circuit, but we still truncate it so it fits in a field - if (blobHash.length !== NUM_BYTES_PER_SHA256) { + if (blobsHash.length !== NUM_BYTES_PER_SHA256) { throw new Error(`blobHash buffer must be ${NUM_BYTES_PER_SHA256} bytes`); } - if (blobHash[0] !== 0) { + if (blobsHash[0] !== 0) { throw new Error(`blobHash buffer should be truncated and left padded`); } if (inHash.length !== NUM_BYTES_PER_SHA256) { @@ -35,17 +35,17 @@ export class ContentCommitment { return z .object({ numTxs: schemas.Fr, - blobHash: schemas.BufferHex, + blobsHash: schemas.BufferHex, inHash: schemas.BufferHex, outHash: schemas.BufferHex, }) - .transform(({ numTxs, blobHash, inHash, outHash }) => new ContentCommitment(numTxs, blobHash, inHash, outHash)); + .transform(({ numTxs, blobsHash, inHash, outHash }) => new ContentCommitment(numTxs, blobsHash, inHash, outHash)); } toJSON() { return { numTxs: this.numTxs, - blobHash: this.blobHash.toString('hex'), + blobsHash: this.blobsHash.toString('hex'), inHash: this.inHash.toString('hex'), outHash: this.outHash.toString('hex'), }; @@ -56,13 +56,13 @@ export class ContentCommitment { } toBuffer() { - return serializeToBuffer(this.numTxs, this.blobHash, this.inHash, this.outHash); + return serializeToBuffer(this.numTxs, this.blobsHash, this.inHash, this.outHash); } toFields(): Fr[] { const serialized = [ this.numTxs, - Fr.fromBuffer(this.blobHash), + Fr.fromBuffer(this.blobsHash), Fr.fromBuffer(this.inHash), Fr.fromBuffer(this.outHash), ]; @@ -107,7 +107,7 @@ export class ContentCommitment { isEmpty(): boolean { return ( this.numTxs.isZero() && - this.blobHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && + this.blobsHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.inHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) && this.outHash.equals(Buffer.alloc(NUM_BYTES_PER_SHA256)) ); @@ -127,7 +127,7 @@ export class ContentCommitment { this.inHash.equals(other.inHash) && this.outHash.equals(other.outHash) && this.numTxs.equals(other.numTxs) && - this.blobHash.equals(other.blobHash) + this.blobsHash.equals(other.blobsHash) ); } } diff --git a/yarn-project/circuits.js/src/structs/header.ts b/yarn-project/circuits.js/src/structs/header.ts index bf35e78995a..5648c55ff85 100644 --- a/yarn-project/circuits.js/src/structs/header.ts +++ b/yarn-project/circuits.js/src/structs/header.ts @@ -156,7 +156,7 @@ export class Header { return `Header { lastArchive: ${inspect(this.lastArchive)}, contentCommitment.numTxs: ${this.contentCommitment.numTxs.toNumber()}, - contentCommitment.blobHash: ${this.contentCommitment.blobHash.toString('hex')}, + contentCommitment.blobsHash: ${this.contentCommitment.blobsHash.toString('hex')}, contentCommitment.inHash: ${this.contentCommitment.inHash.toString('hex')}, contentCommitment.outHash: ${this.contentCommitment.outHash.toString('hex')}, state.l1ToL2MessageTree: ${inspect(this.state.l1ToL2MessageTree)}, diff --git a/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts b/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts index d1c07fe7de9..0b27aee6104 100644 --- a/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts +++ b/yarn-project/circuits.js/src/structs/rollup/block_root_or_block_merge_public_inputs.ts @@ -5,7 +5,7 @@ import { BufferReader, type Tuple, serializeToBuffer, serializeToFields } from ' import { type FieldsOf } from '@aztec/foundation/types'; import { AZTEC_MAX_EPOCH_DURATION } from '../../constants.gen.js'; -import { BlobPublicInputs } from '../blob_public_inputs.js'; +import { BlockBlobPublicInputs } from '../blob_public_inputs.js'; import { GlobalVariables } from '../global_variables.js'; import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; @@ -60,9 +60,9 @@ export class BlockRootOrBlockMergePublicInputs { */ public proverId: Fr, /** - * Public inputs required to verify a blob (challenge point z, evaluation y = p(z), and the commitment to p()) + * Public inputs required to verify a blob (challenge point z, evaluation y = p(z), and the commitment to p() for each blob) */ - public blobPublicInputs: Tuple, + public blobPublicInputs: Tuple, ) {} /** @@ -84,7 +84,7 @@ export class BlockRootOrBlockMergePublicInputs { Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(AZTEC_MAX_EPOCH_DURATION, BlobPublicInputs), + reader.readArray(AZTEC_MAX_EPOCH_DURATION, BlockBlobPublicInputs), ); } diff --git a/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts b/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts index e8a66cf8ccd..d469ada1216 100644 --- a/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/block_root_rollup.ts @@ -5,6 +5,7 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { ARCHIVE_HEIGHT, + BLOBS_PER_BLOCK, FIELDS_PER_BLOB, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, NESTED_RECURSIVE_PROOF_LENGTH, @@ -58,19 +59,19 @@ export class BlockRootRollupInputs { /** * Flat list of all tx effects which will be added to the blob. * Below line gives error 'Type instantiation is excessively deep and possibly infinite. ts(2589)' - * Tuple + * Tuple */ public blobFields: Fr[], /** - * KZG commitment representing the blob (precomputed in ts, injected to use inside circuit). + * KZG commitments representing the blob (precomputed in ts, injected to use inside circuit). * TODO(Miranda): Rename to kzg_commitment to match BlobPublicInputs? */ - public blobCommitment: Tuple, + public blobCommitments: Tuple, typeof BLOBS_PER_BLOCK>, /** - * The eth blob hash for this block (= last 31 bytes of sha256(blobCommitment)) - * See yarn-project/foundation/src/blob/index.ts for calculation + * The hash of eth blob hashes for this block + * See yarn-project/foundation/src/blob/index.ts or body.ts for calculation */ - public blobHash: Fr, + public blobsHash: Fr, ) {} /** @@ -115,8 +116,8 @@ export class BlockRootRollupInputs { fields.previousBlockHash, fields.proverId, fields.blobFields, - fields.blobCommitment, - fields.blobHash, + fields.blobCommitments, + fields.blobsHash, ] as const; } @@ -139,8 +140,8 @@ export class BlockRootRollupInputs { Fr.fromBuffer(reader), // Below line gives error 'Type instantiation is excessively deep and possibly infinite. ts(2589)' // reader.readArray(FIELDS_PER_BLOB, Fr), - Array.from({ length: FIELDS_PER_BLOB }, () => Fr.fromBuffer(reader)), - reader.readArray(2, Fr), + Array.from({ length: FIELDS_PER_BLOB * BLOBS_PER_BLOCK }, () => Fr.fromBuffer(reader)), + reader.readArray(BLOBS_PER_BLOCK, { fromBuffer: () => reader.readArray(2, Fr) }), Fr.fromBuffer(reader), ); } 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 4233ffcabf8..c59ab16a71e 100644 --- a/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts +++ b/yarn-project/circuits.js/src/structs/rollup/root_rollup.ts @@ -4,7 +4,7 @@ import { BufferReader, type Tuple, serializeToBuffer, serializeToFields } from ' import { type FieldsOf } from '@aztec/foundation/types'; import { AZTEC_MAX_EPOCH_DURATION } from '../../constants.gen.js'; -import { BlobPublicInputs } from '../blob_public_inputs.js'; +import { BlockBlobPublicInputs } from '../blob_public_inputs.js'; import { AppendOnlyTreeSnapshot } from './append_only_tree_snapshot.js'; import { FeeRecipient } from './block_root_or_block_merge_public_inputs.js'; import { PreviousRollupBlockData } from './previous_rollup_block_data.js'; @@ -111,7 +111,7 @@ export class RootRollupPublicInputs { public vkTreeRoot: Fr, public protocolContractTreeRoot: Fr, public proverId: Fr, - public blobPublicInputs: Tuple, + public blobPublicInputs: Tuple, ) {} static getFields(fields: FieldsOf) { @@ -162,7 +162,7 @@ export class RootRollupPublicInputs { Fr.fromBuffer(reader), Fr.fromBuffer(reader), Fr.fromBuffer(reader), - reader.readArray(AZTEC_MAX_EPOCH_DURATION, BlobPublicInputs), + reader.readArray(AZTEC_MAX_EPOCH_DURATION, BlockBlobPublicInputs), ); } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 9e3ed8049f1..23b73243f76 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -26,6 +26,7 @@ import { AvmExecutionHints, AvmExternalCallHint, AvmKeyValueHint, + BLOBS_PER_BLOCK, BaseOrMergeRollupPublicInputs, BaseParityInputs, CallContext, @@ -164,6 +165,7 @@ import { AvmPublicDataWriteTreeHint, BaseRollupHints, BlobPublicInputs, + BlockBlobPublicInputs, CountedPublicCallRequest, EnqueuedCallData, Poseidon2Sponge, @@ -942,6 +944,16 @@ export function makeBlobPublicInputs(seed = 1): BlobPublicInputs { return new BlobPublicInputs(fr(seed), BigInt(seed + 1), makeTuple(2, fr)); } +/** + * Makes arbitrary block blob public inputs. + * Note: will not verify inside the circuit. + * @param seed - The seed to use for generating the blob inputs. + * @returns A block blob public inputs instance. + */ +export function makeBlockBlobPublicInputs(seed = 1): BlockBlobPublicInputs { + return new BlockBlobPublicInputs(makeTuple(BLOBS_PER_BLOCK, () => makeBlobPublicInputs(seed))); +} + /** * Makes arbitrary eth address. * @param seed - The seed to use for generating the eth address. @@ -1024,7 +1036,7 @@ export function makeBlockRootOrBlockMergeRollupPublicInputs( fr(seed + 0x800), fr(seed + 0x801), fr(seed + 0x900), - makeTuple(AZTEC_MAX_EPOCH_DURATION, () => makeBlobPublicInputs(seed), 0x100), + makeTuple(AZTEC_MAX_EPOCH_DURATION, () => makeBlockBlobPublicInputs(seed), 0x100), ); } @@ -1094,9 +1106,8 @@ export function makeBlockRootRollupInputs(seed = 0, globalVariables?: GlobalVari makeTuple(ARCHIVE_HEIGHT, fr, 0x2300), fr(seed + 0x2400), fr(seed + 0x2500), - // @ts-expect-error - below line gives error 'Type instantiation is excessively deep and possibly infinite. ts(2589)' - makeTuple(FIELDS_PER_BLOB, fr, 0x2400), - makeTuple(2, fr, 0x2500), + makeTuple(FIELDS_PER_BLOB * BLOBS_PER_BLOCK, fr, 0x2400), + makeTuple(BLOBS_PER_BLOCK, () => makeTuple(2, fr, 0x2500)), fr(seed + 0x2600), ); } @@ -1174,7 +1185,7 @@ export function makeRootRollupPublicInputs(seed = 0): RootRollupPublicInputs { fr(seed + 0x100), fr(seed + 0x101), fr(seed + 0x200), - makeTuple(AZTEC_MAX_EPOCH_DURATION, () => makeBlobPublicInputs(seed), 0x300), + makeTuple(AZTEC_MAX_EPOCH_DURATION, () => makeBlockBlobPublicInputs(seed), 0x300), ); } diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index e0e11beee40..7e4bf7be736 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -10,6 +10,7 @@ import { } from '@aztec/circuit-types'; import { makeBloatedProcessedTx } from '@aztec/circuit-types/test'; import { + BlockBlobPublicInputs, EthAddress, GENESIS_ARCHIVE_ROOT, GasFees, @@ -21,6 +22,7 @@ import { fr } from '@aztec/circuits.js/testing'; import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum'; import { range } from '@aztec/foundation/array'; import { Blob } from '@aztec/foundation/blob'; +import { sha256, sha256ToField } from '@aztec/foundation/crypto'; import { openTmpStore } from '@aztec/kv-store/utils'; import { OutboxAbi, RollupAbi } from '@aztec/l1-artifacts'; import { SHA256Trunc, StandardTree } from '@aztec/merkle-tree'; @@ -215,7 +217,7 @@ describe('L1Publisher integration', () => { fileName: string, block: L2Block, l1ToL2Content: Fr[], - blob: Blob, + blobs: Blob[], recipientAddress: AztecAddress, deployerAddress: `0x${string}`, ): void => { @@ -244,7 +246,7 @@ describe('L1Publisher integration', () => { body: `0x${block.body.toBuffer().toString('hex')}`, decodedHeader: { contentCommitment: { - blobHash: `0x${block.header.contentCommitment.blobHash.toString('hex').padStart(64, '0')}`, + blobHash: `0x${block.header.contentCommitment.blobsHash.toString('hex').padStart(64, '0')}`, inHash: `0x${block.header.contentCommitment.inHash.toString('hex').padStart(64, '0')}`, outHash: `0x${block.header.contentCommitment.outHash.toString('hex').padStart(64, '0')}`, numTxs: Number(block.header.contentCommitment.numTxs), @@ -292,7 +294,7 @@ describe('L1Publisher integration', () => { }, header: `0x${block.header.toBuffer().toString('hex')}`, publicInputsHash: `0x${block.getPublicInputsHash().toBuffer().toString('hex').padStart(64, '0')}`, - blobPublicInputs: blob.getEthBlobEvaluationInputs(), + blobInputs: Blob.getEthBlobEvaluationInputs(blobs), numTxs: block.body.txEffects.length, }, }; @@ -365,10 +367,19 @@ describe('L1Publisher integration', () => { // Check that we have not yet written a root to this blocknumber expect(BigInt(emptyRoot)).toStrictEqual(0n); - const blob = new Blob(block.body.toBlobFields()); - expect(block.header.contentCommitment.blobHash).toEqual(blob.getEthBlobHash()); + const blobs = Blob.getBlobs(block.body.toBlobFields()); + expect(block.header.contentCommitment.blobsHash).toEqual( + sha256ToField(blobs.map(b => b.getEthVersionedBlobHash())).toBuffer(), + ); - writeJson(`mixed_block_${block.number}`, block, l1ToL2Content, blob, recipientAddress, deployerAccount.address); + writeJson( + `mixed_block_${block.number}`, + block, + l1ToL2Content, + blobs, + recipientAddress, + deployerAccount.address, + ); await publisher.proposeL2Block(block); @@ -387,9 +398,9 @@ describe('L1Publisher integration', () => { hash: logs[i].transactionHash!, }); - const [z, y] = await rollup.read.blobPublicInputs([BigInt(i + 1)]); - expect(z).toEqual(blob.challengeZ.toString()); - expect(y).toEqual(`0x${blob.evaluationY.toString('hex')}`); + const blobPublicInputsHash = await rollup.read.blobPublicInputsHashes([BigInt(i + 1)]); + const expectedHash = sha256(Buffer.from(BlockBlobPublicInputs.fromBlobs(blobs).toString().substring(2), 'hex')); + expect(blobPublicInputsHash).toEqual(`0x${expectedHash.toString('hex')}`); const expectedData = encodeFunctionData({ abi: RollupAbi, @@ -402,7 +413,7 @@ describe('L1Publisher integration', () => { [], // TODO(#9101): Extract blobs from beacon chain => calldata will only contain what's needed to verify blob: `0x${block.body.toBuffer().toString('hex')}`, - blob.getEthBlobEvaluationInputs(), + Blob.getEthBlobEvaluationInputs(blobs), ], }); expect(ethTx.input).toEqual(expectedData); @@ -471,10 +482,12 @@ describe('L1Publisher integration', () => { blockSource.getL1ToL2Messages.mockResolvedValueOnce(l1ToL2Messages); blockSource.getBlocks.mockResolvedValueOnce([block]); - const blob = new Blob(block.body.toBlobFields()); - expect(block.header.contentCommitment.blobHash).toEqual(blob.getEthBlobHash()); + const blobs = Blob.getBlobs(block.body.toBlobFields()); + expect(block.header.contentCommitment.blobsHash).toEqual( + sha256ToField(blobs.map(b => b.getEthVersionedBlobHash())).toBuffer(), + ); - writeJson(`empty_block_${block.number}`, block, [], blob, AztecAddress.ZERO, deployerAccount.address); + writeJson(`empty_block_${block.number}`, block, [], blobs, AztecAddress.ZERO, deployerAccount.address); await publisher.proposeL2Block(block); @@ -493,9 +506,9 @@ describe('L1Publisher integration', () => { hash: logs[i].transactionHash!, }); - const [z, y] = await rollup.read.blobPublicInputs([BigInt(i + 1)]); - expect(z).toEqual(blob.challengeZ.toString()); - expect(y).toEqual(`0x${blob.evaluationY.toString('hex')}`); + const blobPublicInputsHash = await rollup.read.blobPublicInputsHashes([BigInt(i + 1)]); + const expectedHash = sha256(Buffer.from(BlockBlobPublicInputs.fromBlobs(blobs).toString().substring(2), 'hex')); + expect(blobPublicInputsHash).toEqual(`0x${expectedHash.toString('hex')}`); const expectedData = encodeFunctionData({ abi: RollupAbi, @@ -508,7 +521,7 @@ describe('L1Publisher integration', () => { [], // TODO(#9101): Extract blobs from beacon chain => calldata will only contain what's needed to verify blob: `0x${block.body.toBuffer().toString('hex')}`, - blob.getEthBlobEvaluationInputs(), + Blob.getEthBlobEvaluationInputs(blobs), ], }); expect(ethTx.input).toEqual(expectedData); diff --git a/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json b/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json index 18b51311048..97470ed164d 100644 --- a/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json +++ b/yarn-project/end-to-end/src/fixtures/dumps/epoch_proof_result.json @@ -1 +1 @@ -{"proof":"00004b640000025b0000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000009c00000000000000000000000000000000000000000000000000000000000000012b9dd7efd8c7f12631d28370f677e6107b777df7c2ac4c85d763807648ffdaa9000000000000000000000000000000000000000000000000000000000000000223de7ca58210596d7075b68f3e26ad950704188ebfc305c4a3da5ee4ba3aaba600000000000000000000000000000000000000000000000000000000000000040c38c7bfd4b3670748ecff205ad66ef6c837c670c087a3429114ad8698a1a5bd2c44779752568b31bf914dc1a4cdb7e69f00048fa99dac478cbd5040c48d781b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030581ee1ac27ddf3d4bb1f0d6404fd67ed40e9a8e728eaa78bc1c438d3407e7927d6a49f48a8f07db1170672df19cec71fcb71d97588503150628483943e2a1400000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c51e7176807947e96000000000000000000000000000000000000000000000001c2fafa7f255983ba0000000000000000000000000000000000000000000000007b54e2f78e7c1a140000000000000000000000000000000000000000000000000001ccbef73f995f000000000000000000000000000000000000000000000005d0e2ea8295d58c190000000000000000000000000000000000000000000000059b3e79cd63dac5a5000000000000000000000000000000000000000000000002c15d57227ea439880000000000000000000000000000000000000000000000000001b2b42986c5ba00000000000000000000000000000000000000000000000c80763da2b019a11800000000000000000000000000000000000000000000000c4959d528650dc502000000000000000000000000000000000000000000000007caf78e9461ba904d000000000000000000000000000000000000000000000000000195145428b9fd000000000000000000000000000000000000000000000000aba2e910a05d5fa3000000000000000000000000000000000000000000000007d503ae05e67eb8cc000000000000000000000000000000000000000000000003d95823c10852558a000000000000000000000000000000000000000000000000000233af3936438b00000000000000000000000000000066b5bca25eba7bc41b83d593d3021e3ee000000000000000000000000000000000002f9485846c5fabacb0897d9747bce9000000000000000000000000000000129ec4256c6e6b7d1b3a38bd1cf90a62e400000000000000000000000000000000000cf6e9c2ff4eb34f2a15837ee77ea200000000000000000000000000000090d81363d18c48656c9f0f4b42ca42e9fe00000000000000000000000000000000001d738564de24c22dc9acd9462f504b000000000000000000000000000000855d56ecbfdf98e190fb31c46704b04c8c0000000000000000000000000000000000030bc8b72956fe3eaf99433f3234dc000000000000000000000000000000531f182b9c35c754e9153e6f89acb0d27f0000000000000000000000000000000000008dae07d74087d77472b1f71cbf3f0000000000000000000000000000001b027c0009305e53f869e50c47f21be06600000000000000000000000000000000002f99c73e39f3dfeac0ee02b09d3d5300000000000000000000000000000024eba1cbffaf8f4196d7f6f82bd5bed62f00000000000000000000000000000000002e44b96fb9dc942c716766c5098d9600000000000000000000000000000071772aaa9d0de4691948882169ee308d430000000000000000000000000000000000084a44c23aeffc619c84d1f84df2720000000000000000000000000000008b094f2e2fbd2bfc9d0123d26c9a2fdca8000000000000000000000000000000000003b4f947cd0f6a54760e5df757134600000000000000000000000000000023e3f180615c14ae4eef7711ae7be4ab13000000000000000000000000000000000005e3308e8d1ad9cd86677acc1fc38a0000000000000000000000000000004017706995ab86727eeab779982da9c6db00000000000000000000000000000000001f067ae14dc06cd1c5319a2def7530000000000000000000000000000000240a9b3e6d96bc276e2f88f5a6fb50a07600000000000000000000000000000000000217fc65349da83a2fb5318f306b1b000000000000000000000000000000fc503fcbd8dcbfaf0e6a5dd58e199f4f9a00000000000000000000000000000000001b2075515311947e5225a4360cfd200000000000000000000000000000005f2c552ddd7cf3a478fd5eb0ad5529eaa900000000000000000000000000000000002ace5e72c2c3dcb2f4c4895233b848000000000000000000000000000000d8d8424545a0a58a99d91f8c10c40ca4f1000000000000000000000000000000000019b66b07d04e8b8c3f4c1ff27abbfa0000000000000000000000000000006c6781df2e8d0618955001021953426acd000000000000000000000000000000000020673cea5d87828bf46e03924c124f2cce12e2ce8938c0f65979d03264b6fd55e51651330d469151f921a43664874e03963b9012a86768c1f6cbe64f1ca15fd24ed1f746ac29fff1e8d3efb99b78b318407a547bf00dae54abfdc0c0d51173f249437481cc5705c170d4ed300757e02f4df18aa0c66b07f46e63de4a7ca2639bc61a88b212e4d2510c5ed1f421fde62e92eadb8636f7cd6a4b4a34c245f607bba9be741af452999ff38d635db58b760ab9a9a82bc4b93bacc19171adefce73eaa09fcfae67f846b04cea5ecc19909e0e5fe1d20d26c478be09aa66dfd14fa2010e3832477f3a74ca42f415ab2b456016b8431a7fcc85deae4355f1b2dc0b58c9433c37efead117ea9182e8d3c17a88254b5ab6fb364c3e4ebb8d10c3d8d399acf04b40be492b7f509dda44d183940f1eae9fd163cd922d6fba1267648e40da8c00b86351b19e428d0dc7f3e155426c18c93484e32bb15b8e00715a998aea8bd42316a3eba9a416864c02ac67f4630d08f395f45e84a00c7b2988556fcb08baf967cdbe7c02a7478bea71ea7ac8db1b025e75d42df07a1c67f77495f0553fe527a680880337bea638f651fd8df12c6f13cfb7a9eeabb3838d1bb590a51c4c1d71650c6629ea0be5bc62a7c444cb04702e612fe530240499d54902ef140da55819fbb79642c1c4b195dbc251875567e60cde113b4e6bd40d958b3f3d107d8436fbac59840b5b0ace3b2ff0e52b61533505ac480fbd3247521834aa9e2636aee77e35d108cacb037a73e24efee6a41d670b1017804a4080699328befa57f6b76c6cb407c7937197bcd895ec9bbc76af7605a50180f465cfdda3afd64a5d9f977f3af981e9c1eb7f7d6b02e9b760a3714b2b5b91072b5df4c412c505537fba33a432cd45977209fc1e04f521f4df53e486082e0258cd306b5b0b48536fe047c5801a0903f2e2f8575b99d5e8c5ead722ac019603aa59af3d9d4fe2f152d66562f102419f1bf9ab484dde6a5044b2b1ad8200122fafdc462811d274e2164e9b422c8da8564865718ac7acc4a1b3d26eb2e52874a3c9f4925d74268cf13b1fcc023ab10676ba76ff9192608542c8995ed7c902764047ce9d1f8f0d012cc83437d834d0374e4134ce489b78507e2c7efc5c71179801af70fc0a9bc03640bd51c0c05d7f62af15874c8dbb2d87f3a6c25eec9a25e8cc99a9b90707257da7f023f6ad68bf88cd18055e4455dd981a0057b24a8f2d8b17ed76becdcbb83b37e4d0919ffe581d09f973cbdb356d917b564dc747841f399865e392eddd64b83d2bb3cdd85e6fd575bf6c58b3a0b3112517304cbf2a0ca8988a7c6a2bd57e8e445e2dc8e9e9c3281addd99d1aa5c64fa350fecf540b1a3b464395fd4cdc770c7ac8381e05d104a3d02c0dfdef472be040a44289a1061f7d36171bee725fea09c52a1d342546bf3ddb4ba1814d78fdb06fb0fcce3c230be3e0fb984126a9025c86a9a26179e3111259bda8214d38ba067d463347c526040a860abfc53dcc081c5fb1c90c5397cc210816f425b7d73b39e33dd9c8d6f5157866a4d1d2ac319d7e7df8e3b01a0552e2b077b49516a71e5ac9103c12478519c911b2dc2af14db877f1bb770b06443297d6c30ff22c34640b293b2c592c8a2f0076e2cae43025be1b153e90522412b7b90b70ca159167d4c1c98dfecaf8f418168a007b0792537de7148d66685c76d5b860ee76d94fdd9076991b90e14e55286f358a986b9c7845020978553839dda2a2cf6165e2d10ad3104aae803559062d362f0e9c3c241ef6b5a68a67c3cee52cde44283408ab9b3394ca01e2614c7b1f2315f357e8a4089ca452e3219f1ac32ccc9fb8dacdb92808a864cda0c31d6620f784d401f76b213086d3253d7b2b92373e1115e97838ab2b142d0d50c746e62fb2dc18f45225f55a62010e6588cb80f0e6e3748df746cc7aaae0e8868f0c3311ed449bcc42272d42c25177c67326cf68fa9a230a5110fe3e93cbd2064c9ce21fcd6464d5a24c3a81500f8954c6c077b9c0c2891f0d9e09f4d3e6c7e45275631eb8289897c065737cffa1f98a6660ccf4e693d79240099e701e7709d96a59a61ac471a4edb2e8de448116006ff889675717ecf6dd9f7430c3cf75ceed8f906706ed60462620c227967050d8a18cb5154e623c9a3a44d2c590c7fb82cb0352442fdb889aeb1f6fa47713708d59fcdba976d76c3bc22b3deace5b89d58c6fb8fc09c1234dd6ce333bda24f8b205086271cf5baddabb7754833d066b681c3d2c0d27566557c39363dcb5a7a626ce76813c5d7fe402bd4dd36f500b5632d7a00ce71588914a41dc8a2cb338171408efd8035cb223e60ab63aa2006fd1760323aad72071b7068dc59a08b3c7df7b1a29ffe642dbc3fc792d7339a4ded14e59e02489063d4c11d74a3ee623dcd34facc209096b7a5cd55e7f57073c9dd176008db7090dfaa304ff55a4a7e4863e53250a7e542250254028b5bf8ce1b56163978b48c501a70616099fe56f2782425429be5bdbd9bac282ca2a0c075addd59e71b04fe125a0a578a2db38b723c12fb657a7c66c1b7d3f78bf7d14b21ec21b64e5f419bc0f622d2c83e1d8923f0ff9177a656403ff31c99f0c4546e9e33718c7a191a9fa0e99bae5d72d4bcfa240089f160887ec817f229b56e8b11309a02a3982fc383825fee7345f012b224c85126da830202c8189429a1ff08e680e7fd44555280e9f08e39ec083bfe3320bc09c4e3cc632f1585a2336cc110b1b64afc68028bc60b0276a268eb7227ca8ac39395ed9174bf921c362ac37afe3baf99166e1d3d8e7c22def79dfc193b9db35be411c5134b9b66c2fda8eb917b6f8e1c7412ebe0ef14919f57a9c833fa8356627546b0c4f07c6ce1d820cdd17a9f5137a9dc15dec387b0cad21302e34d498f2dbe9edd97b8c19c650042506541eed6c166621ef5e19252f7dca955664ca4139accd708aad34cf7b152936408a04c90b19642912727c73140da9ae1002faab7360cf2836fc94113532396b7ce97c78d8bf19ac755a60100c219b347b519493a3d14466ad18ee49631a67eff5b8d652a148687d13cc6c7120c96122a7b998f7d1d9461a86adacdd631211472e9ffcca0290874f27fa6e9217a2eb0ebe569dfc94616ae0cf5e87a52b308d2dc8c8881cda2ff7f3eddb550728a66ab2b9fdcb3c99523d3f236eba9d8ac7c6f0d6c1a68dcc0aefd8883c33f020c4b6776fa0f448f6f334a99268172333727bf585ce411381e757f284ac77500098fa4b7fb2491e9a49759220d5ca28ab698c1759426ac4fbd3bc2bc15dbe6f00d180b07288f53ba20a5264e3882becbf555188dda5020e50761a9aa9eb5fb215d11e80499be88afaeebec8ab6ff64014f2c60c377131bf50a798f19fd8b8041ce6369e797454581368c85b7bb374073fcbe299f11e0d4649ce013f645746260f7e24ae44debb6bd7fc1a6cbae0face13765bc00c8132437e7a24ec3115699a1064dfe5e233dad7e1f464e7843d375dba9a25c387d9e8e57b918d3d5cb8947b283e3311144d935698f86a134f09fb23aeea54735c5a295c4ceaa3a0672d54ba26a64cefb840311da2fb2c63274c2dea264fe6a503a98904d0d4dc15a19165b701848af03d7dad5b0a3da36c414f467565fb13c08ebae60cd6c29dc530167e220d5d090f7ca9343fec65e74a0d39c73ef548d8bf8df8a50b0dec3aac51884d2b24d38942baaed057ae5149f8e3afc1f408f07ca7a3cd711f4f53d4ae3e6d953c02b9e5dbaceaefd047c324b0e608600e8e763650353a6db3c0f744726c71d6ae05a88e3756600f3c06c4cf05b8577d579220c06867b0563d9f4505735aaa834d0bf142004ee9b5e2b22ec1b93a70c9583e56b23a6aea49172a8a16839b105ebe02fdb762a47c1a21d6c4d8e629045aafe8d163c6bcc6f24c9d6d6f3c1e4450d329d4045471da42fdd5e24e5f16d3dc75d6b6aad0824db738567ae555bdd517d00c1e912934a73760931439e1ae219e346f874d113a0f772a27814a686060c6aa1d20a8fbefba0f23458ecc5fda25559b17cd7c8ed6292611ef047fe2bebc785820de829a4aa9ad936295697d9818c3a2f787f482ea301aef06d2c82be37fabd801cab08aac4a3ac01a55592605895b25c6dd78decf5b1468a41f9f5ebed44fb82a8130c0041fc15b2175bec0acf993392a632afb27236abd95b798c0b38651300b0b689f855a4d6210698a47b6d43070706202c0831f0a63145144dd24b07d13255dd521b078c979b54d1da283e7594e04e789e24895e800107bdd351bb96c1e21d667950b71954042b2ad6aa0807776c901d1a5f1f256cbff220f5a217eba700610f9a08c74a3a6df51ac866f1822d8fd9de4afbeeb6f63ec5c3cad4ba3a4780fee3923863552ac0ba57efa9df0717f0d87d43fd7038e046acc24f1bd0b2bc01d2751f7a8493edcad6b733f7fbdb9fda088f6de53bf4ddd94a7d318e77159ce1d8f0b0466d1e6a21fe6e3db11bb7a2220ded521b1f6b420bb3d216c166c1fd11ee28c2d3624a2dc0a223de837f6f881bbddbf90aa8a19e90a63a0086d3147ad2453f3f6474c4de436d660aebf77330ddf74ff649a6280ecd181b11db40ea54e22bea51aa6f87997d3b9d56bfd7abe0c524761c8ac3013f83d04f124503fc73b2bb6e14a284cfed9aebbbe65891b1e91b2f28c504a4f85c62b5733d94659419e203ecad421aa3f64a8af6c8da7c37b9d82bafcd371f58ea48848775b98ef09f602c4703ab077504ebcc6d221962e64679af92dbf29dfd5415b25d04dd5c652541a21ec51b6f2cd39551b60b65ce2702673b462de183b6479c77678ca589b66701f2ef58072e1af82abed21f8c1e808f527b80444aad8a52ce7f872ebcd177c6d1690bdbf7802b4f6bf1298b7faa0ee2568ae209e7d04b7edca752b049303609c23e1c7a55f3af87b360ed19e89fb73b1a93b6ad41532c89ce3ea5c17d65788f415d22330b0d263e309345f7c403d151b1b43903258268b7cadb079978eaa1e8b1e89a69f6d1c2a612725bed1c34c5c58663e937d3af85d068bd59d20b4b375c2258848a0ae38b690f859389be92f4a211e213847544f079d8e9e7d08687b71df200bc37a562a41294f42cdb8d98bc8cffdfbd978db42e818f662c5c3d58881202f2f3eaf29408c335404fd9a607b9633a5e5aa8797ac94978d45a8f4abf6e1282166b5a6ddb638415f9a9ef52be59ebb08dc6556b49c43d4ff022b7efc824f1422e4d88c0adb33b8dc907c6b84b208b852ae488b256b690a31ad4c636c1a9d242d2a4fa3c6969a57775efe94b9eb249cbf24214f7fce724cd17ce788682832392bd878b4bfbc762349e42a6c5e7e3b6aeb8cc0849df204918f3eea3c4785f96a06651940027ec991034fdb4c9157aa9b79e62b14cb081cdb8e8ae449abf7d1352d35cc5440ad94981a5d259ed03fc6c2342579f694576c46b5f4533007b9e8961935920a1608d31a0992b3bd98c073fcb021845a9dfabd1d555f49e668436f8411c9cdb5a0a53a3b7505ba9efe19215b396e8508ca8c842d669b365f2d445d150276404f4036bb75b025f20ce79890da72bb9faae91dc092b68243209307c957162fabaf0d3b62252eab61c7b6dd1e6b0e79177e0f40eb9a563d3021e17d1cc6115bf372f87d56accd89e14679643cd343afd2b8329371bc1a33f1663cc74f1a1a40ddcbf29afd89191cebcf3585973e0e194d3e87df5b4670ae0979dc9d5a8d15579c95ee402939ef26adf184d6a9ce39497a6508194370d17d7ae0c54a60da0bf71831f323a20ad7240151f54178fe52528f5ae8961ea69e8fcbbfe20037b81a645919de853bc5830c732b775dba24cb8ce35e755b2f24a5c6a6ba570cb6350dbb1364dc80e420fd42e9f92f78990ec8249a4d3e5a51cb27dc794dc7c439622469dfb15c4670eed385ba51418287f94c70c371f22210e1995c1fff87ebb60a09894f5506c9fa760bc4b1c0a0837e722d9500afc6cab78ab7920007753ec920246a9cacdceffacac2c30a3f67184ae9169266e374e7a53e4e4cf6b3a17b22331a5aae8aafd9d4c2637c6d0d777cde134c3de779fefd4171348b6b93a0980e8b05d96a513920e70c20297a02b68cba89ce58f015630d53a0acbed708396ff8192a06b191213a781a6232abdd6ffe54ae02a73b64ebbc2d4874ad577a533ef9b2274aca844b6f43f6954c81a7457dbe95582c266ca9d0b0b081163bfbd495bc370581c4655c821dd7a2e264e610dfc562bb656bad766998d838794483776e45790928faa976ec1adce05ca9d682661b457b2f28186ab6ae91e2c78ec57ecaabcd06c65f788bc9d03b64b36f20d34cf5b244246abcdbfd5162a41e0fcd1094e360228050946c87a783eeba48941b54f4fbd9fe986be085c7c1368fd01610133e590db33cbc8812ed8111360b8dbe77e651269335698f44f96656eddf0516ddb2661e6824fd2de1b09d98c21e1656d69076f9594dbeddfcc5d1c04e65584f46a7022fee44384864e8b6a99d13f26dde69c7705fdb9d3faacdd202e85b772e8066eb152a0f33c85f001395229572418efe57414e8a0b132aa3df2de18fa901f8369e13248a6dd2c1ba18fb4d3340a75c0cab9e6005a397fb22028005d5fc5a31000b1139461cbe3b3b326a7e450e927593e8d7581a034d22e477986188b55682c6cc2685106af645b238b96e6a2732a734bf62dbe54f70ffffd9e44a8fba41643660223a660f985af72768e75a7de9eb91b194f280ae552d3ef56be52f32befbe77d11cd6abe0a1839e6a84684496bcded07f8799c0e2b2bb375689ba0de02fc2dcb0f855bf3ae1a80b43cc304cc56d4f631269525fd0858bfa3eeb6513f8a8a4ee01404b31cb2bc2c444f7798fe104e98d5900541500f88b49b6a5aaa04e4dcee5d23707d04206fb4afe38d2dd21630d66dfecf6a6ab9094217941e25ee15aa4b522bf6ca4d102d35c9680768d6dce9fd9ab329730ad5ad86aaf0327a4fa39df5df06ed284acb82ad5dafbb141e6a5ffb2ddd2ca3057b2638bf680e88cc859b2e302bf96c11daa387c04d08a3165e0d3e45bc2190b77cdf396cd0bfc2c35809b104059b0eb03ba8254ed10cc5790570e836e3dd4d64d48682778e7d036a5ae53ee52f8c39d05daf90a03977ba29b4094ce2ac17ce50c229f4f3cd1a508dbedcf2d827ed27f031e6a92f0bc8e2a6ebd8b2ca73e24c6507f8f1a177fcfa6c134fab72206afdacae2ded26967a89e6dc2d57c4ac9a23c8dc8d8ce7849e4400c0a8e5002699f96b84b0c23ac68f63a5ce61b99b35e81a7daed364324bfeaae0fdda7ab609997d316084352e3d3c3de2f3815ea7f147c93a578e0a1c80cfebd463044a9c118e7777d2cbec2dc5e11d20059a90b4045dd91936b7a76df7ee120903479c651113a780f0d6f8c053708f54496c7bf1f6cfb920d2dbe12bb0aee4fae2379fd411c0aa4d51a7a91f6e7c1085f92519e7e8a7d75ae980c8d69e99acd333d6603f2334a924a925b287dc390ccfa57d32b50f47d7ad5430670f2fa796536e67b3a2141cc773d3906942cae8c0bef3b97e73857816b23cb4f89b36a6fa461e7d7ef6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001962d74615a283539435993631e1e3b8b08cbd25c2911064bece8e00abfcebda17bd4876f383a5fd688ea9c76d8e0fcde6a75b33874d9a71ef6d4f2ce106432f105b95620e62f68a85b4b30725fd0bae6e3d63237f602afcf1614611f62734dd02ba72868790b29a306bfe09390335837bd988c7790bb22db715d3ad502ceaac0575a9c541c05f1aa505906e894762aefbad8886e270042aec0aae31e8df1a5103b94d7015682beee7855cc2353ab17b293a727e3acd709a4e5308c0a26a212a0ab91f5c2ad61920820e8b879ba02355263adaeb79a3c96d1c1aea4af2ac70760e75c59720c24786db5ab1fdb726e8f8d0309ecdedd6f48645344783107f8681265b89e45b99560a55ec8763b5f4927d4f1aef9800da2369f8a0a28dea459b9019b8f04f5d2312a5491e0da0220644fbf61bf1b9e435a36838117c7118a5b5f000887ab4bbae308331669f30a7c706edbec3afcdee8821bf56b523f43b0821c72ff689c6d8d97847fd81e3ca329539b43c72b3e180ef28192f61480f4006c25f019b9e986d7b52a8b4c3be77830233c716a324a64650ff6e0b5f5f244d3e7530284f41a4cc93255f9725df3cac20afdfbbb3092ef29ce002d70f755b068ef38419e4211688789ee8aba2384bed59093cb88a7a29bf365895fa72ebeb4e1ecd6c17535b59164a891bc5a4b199a62de22db56c6e31b3618c777b0cd483e27c06f51187d8ca7cf7241fa7dd4df1aac209c2bb4681776fad34a78d18b83db976c93b1b317124b6ecf4c5f619ee876f53c62a5230b150fa7c7d8b9169940c3acf42d3141cacdb5a879946052e2fe60d26ac0a4c774e606b960a8ef28f2399b1c54b89157357d54026d41027073d5d802816303ea2d31d236a736240b27a1b530bf9891ef5f11b0a9994ffbb9290d17a54658b3124e5e4f12cf178d4ebf63cc32eec5c273dee225ffd3ed3bf71daf8145ffdc3ce12ed27b22fcbd79a483647504c104c066e46e3f736757e23c782db5dbe1b31f162563ac12e35eea38f8d1d0f74b96b1007227d233da0c6ec5e6ef2c76ff61e5f1d667654430c0af561602736aa38bc25874587a106feca28750c5c92ac8506cc11509f148723acd86c1d518c960a7b21d40263936ff188371a79ea586e592552cc8f97f0779573ef04ec29c150212c25cfbc5c178f434e529ebf56ce56e7df6c45209b7979722a901c4f36672d49a82244eb697a563659a51b630f3eb53386d96d96e6916d408bffa3d642546e60b622e599db9d1007f422f686b5a61473d9921a735823ed4166a5d49405fd336ada1a3d17b929a43f053b4cfe5b69ebb95fa48ec564dba1924aaf2162b2a0f175d322a5e96822969fe3ba3d64c5f71023e4065cef34819475f31fb26299f2401edd2dfa5dde8ffb761db6ce9882411fb633e1f8b6e25f8b1ffbd79b4e2163df4cb8208d384e2cbb949c3463ffd86cc694f1228ee429152723d82d88f0864a78eb4a1f2b70a795e25371c7e6ef958e4fbedea9f9675fedfabc58d74658def1d388fc0be3be433915c545b7cf994079e597bd0153a9b6c847b1524c71d7738332875a0672f4a15c09dda9ad6cd64e08ed9399c683799f878084723f22a1d3ed3d9fd118a6c532ccd01264d8de26b285d2d8f7722b62146194b132117ac4329ec6fe3001930da7d268b30cb1e492ed812749506ae26d0a05ca709ff87f7cf3d2247c861815f9c8877c3fa50e2ae3e5af89c13147e661513045669eeae9982f978770a227592f5ddcbf75f3f70eddb0b2f05d1a7e0c1bd8153efa180b228452548aef291eb5e1ac7558947c8c35eb5c7a74c7cb202b8a9daebdaec15ffd1f5bf02b29572ba310802c8f5b4e4f093168b21699716118fdf31aed4eecd6437c771fd4777c008b8e8e3fe95b267740f80e4e8b7ead6adae9b5803060190ec9b7095045a4242dcfbf8ad754ba8e0d9c16ceb31f47035d84cd957fe949d94f275eb171c4d948000000000000000000000000000000ae294754c5bf76c9701715b9af044533d0000000000000000000000000000000000006241d85b1b2d046bb0e425225750900000000000000000000000000000020bb5b6833e2ee8ab4bf317b8f622e59850000000000000000000000000000000000153e8412c0a31b4bdf0c9d88501e020000000000000000000000000000008c2200b549663ab5a74479cdaaa63c7e2300000000000000000000000000000000001ba1a1eac7e0a6e2b0c51f2af309940000000000000000000000000000005a10789234bed9ef2577615d87e4e18e5300000000000000000000000000000000002dcc0114c72f7305b21560a8d4ba6a000000000000000000000000000000fb31f796293d5fcc16b198146be6b3ea0200000000000000000000000000000000001f5c096a286f1b4ebc5d618878acea0000000000000000000000000000009aa3f460e088797322bccc8c9b5c21078b000000000000000000000000000000000025ae4eb97ce4d82a080366c9af891700000000000000000000000000000093e0a27fbc1d9b1fade1199240b72de3f7000000000000000000000000000000000015cb0d51ecded3cfd7be0613f3ce2e000000000000000000000000000000935fc51491804b71617779300dc01877570000000000000000000000000000000000275c796f15c51585a0fa902439c43f0000000000000000000000000000007cd1effcf6d0cb4be93f966251c236fbc8000000000000000000000000000000000025c26946977545a42efe9279d0b48f00000000000000000000000000000080ed335dcbbfbff49ff5483ec94701d78100000000000000000000000000000000001ac849e088c1bede1261e4730868690000000000000000000000000000007a4e2486f21551259d964ac533d4869b1400000000000000000000000000000000001958475b4e55025af48e455779ea000000000000000000000000000000001cc1f48c097b207b5c6e23985fb5621ce50000000000000000000000000000000000180e46a6bf2582b4a4443ee168720c0000000000000000000000000000006455ab8e53f85e0b45bd1453de9c84de0f00000000000000000000000000000000000efa31591ee3a12f599a1afa12138000000000000000000000000000000098221891bf61bd6f0e63cad6493c2587d00000000000000000000000000000000000065c20385ef2dc1389be4aa534da1c00000000000000000000000000000096f6c7619fef3685a83d901cf340b05a2a0000000000000000000000000000000000235404aa853801bc66308651f66ed6000000000000000000000000000000147d94680cd9a6e5fa1f3b1256b98826c100000000000000000000000000000000002d36fee90de387dbe205b2505f0bb5000000000000000000000000000000ce0d06dfeb79c9605564b7f93a062bfcc4000000000000000000000000000000000018e3db215d5d64300960f28dd94196000000000000000000000000000000da75a72dd0dce564967a3c5d1871657a0c00000000000000000000000000000000000d3a0014506bae5674b5b09f5ad252000000000000000000000000000000cba921167c7badfd2c7307996dc6a3bf480000000000000000000000000000000000197dd10b219f3d7e3f61bf3801ef8c000000000000000000000000000000a2f281dc76a515c40b42c9025e2e6ca0f200000000000000000000000000000000000c68946c8eab0db850eeb4184765e5000000000000000000000000000000105e4db71a88173003bfc168d17fb170ef00000000000000000000000000000000000f63bf11478b1eb86ffb9c53570104000000000000000000000000000000f9853437822880329289c6bf73b445929900000000000000000000000000000000000b8f2f0dc500c4156f515261831aa3000000000000000000000000000000a6cb8f0fd3fb6352112b0cb4175b65b77c000000000000000000000000000000000017a7ead6db6d84bd7f868e2321b11c000000000000000000000000000000953f5a2a6745f076ebc02f6491d57b11a000000000000000000000000000000000001fa430abb2c99ee4e6816288e9370d000000000000000000000000000000e24e10d0d3d76b82871af8b8cb7b8fbf0c000000000000000000000000000000000002d987888114ea1fc5bc3abbf951d6000000000000000000000000000000c37c0f3b9877dc84405a937d7de7ec6f0c00000000000000000000000000000000000aad6d5b8f4f1f6abc6ce7dd548139000000000000000000000000000000c3b88213f13a49ece55e4ae0192ca7c071000000000000000000000000000000000006653ff991b6772ac2e11e77181ea80000000000000000000000000000005eed04aeaa42be39e5714ea57121319616000000000000000000000000000000000013ef5e65070c815830a343d09a3773000000000000000000000000000000cfde279800e2c417edba6c16ea9d65586300000000000000000000000000000000000b2b44042c4615e05ce066019ab185000000000000000000000000000000d26bcbae263a4a819dc4d8df8490fe30cf00000000000000000000000000000000000734011f79e5e9ef6117565766603200000000000000000000000000000086aef3356ea4b4d7192758ea87eb19d18700000000000000000000000000000000000e283c06b6f9779164321b5a6ab6b20000000000000000000000000000006aec93d41b202950082626986bd34ae72300000000000000000000000000000000002c9cd513b6890c3eb0ff65eee2bfc700000000000000000000000000000032a08e68ac0d71ff5554c2c283493b6d5f000000000000000000000000000000000024dd8c2b93022a697f6dcf70e96e2400000000000000000000000000000060d935060718ec8cb127ae7ccbae77ef9e000000000000000000000000000000000021defca84d2a4ace81c37b5f23d038000000000000000000000000000000b532272d7f9ee780a0055464f992462c0100000000000000000000000000000000002ec40ad94968d1dbd0e9c4461c8486000000000000000000000000000000d7219202ed1c8861bf53f657ad563a28df000000000000000000000000000000000028e62cfaf67ae82ece0de98d3e2f850000000000000000000000000000005828c09d4fa2219c2e40716e161e61fd6f000000000000000000000000000000000008e5f422241a301fc395cbbde020380000000000000000000000000000003c362ec8b49568c0fa65b07e6cd419977f000000000000000000000000000000000024dfe55e18ba66a0b9bfa2f90b601a0000000000000000000000000000008d4b8f3c970806b8f3a129dcf05575f53300000000000000000000000000000000000919d9aca599996642589d1b2d36c30000000000000000000000000000004d6e9fd485f2bdd9fa82b95de17b13d643000000000000000000000000000000000024948eec7dffad2429dbd1085a18b7000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000003b41fbb355d83145cd303646901f3a8761a77e0717036b186d2b862929d5a282db4eccea98f8499bbdcd8abb3a8e67ecececa279a6dd9a1e5224588c27814ca082f5e0471e47b5d8669d7b131593a68809cc16872e85697840abcad10c3c79a1136d0cd0e249e0e60ed519e17bb2c4f94891ae0d1cb639324f776a4e9f9b671285d6683b4c56a6c7d0931f87f56aaabd297e5145e2a4d4da85be58b4be3916929970021f7947f9ad2109df8a1172a07db4c64a301e3d57b7af6133d4b7ce18027eaf4623745ef6cbd672d78cf2490284f458794535f48e69cb4dffc3e3f9bf81fc5bedbbf58327ef21f5a55e3c89a573b8f2555a4aa332d449b0cc6a5917da92cd32f31e157b42fa45271c29bd502a685f9d164725192caaec3c17740276f0b1c582283800dadc1547649fb120bc612e303467502ea74605f8504fce95558091379ac804fb5c3b0f933e8b8ff2b8957fd7f03a7e5ee9c318144c031d0971de918135ec942534cd90df6706d7087d1f34f1288babdfbf0b62f0ff2aad22e2db32251fc7d61fe7fea401a4195dc2fd2129d7f816dfdaca40a187f59a2611128c71e8932f0395d691eb876f5cda2c759b4e7cde19cf7e7cf111eda9faf61f3106b2a040f8e548b43183206cc934f903a2015d3e330ae5364dd7bb87d5b93ca2eb429158928c15076118553891bd6f9e6b7c3517516cc2cf96817eff9fde8add40d301abff29faaa46d288e7e3c62cd2d419d9a6093c2f65f91a9bec1c85f75ee6519f940e40ac9ff9c9d76084cd5e62d2d460fa8838dd89355dc9398e86ffd5be72488749e062ef020378cf781bf57ab0a1b017f55a3e9d91123d92f177881f2eb1d3c9e32aef3713b7aa8eef2cc8788f5c0b21d8364a47287c1b0de1e1013c06622be284c5db92dc139daf747ae936401764e92e82f10ed12c21e70b51e080d0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009530ed940f4492e4eb9b44bc663a401c7a00000000000000000000000000000000000dc94cedc2701a4ffb589ebaf4e0dd000000000000000000000000000000950b78e86248264b77e78541986895a9b5000000000000000000000000000000000001b9aaa6dce1746f6b9dd5f03c3fed000000000000000000000000000000c1d3e968d0cab6b139498bd9b1120c255900000000000000000000000000000000002e52bf3550785c44826e219ef8ecf000000000000000000000000000000091423ba624a0b7c55077a94cfa6b43d719000000000000000000000000000000000015227e83c75686aa959b79bd0fdfc00000009c","publicInputs":"2b9dd7efd8c7f12631d28370f677e6107b777df7c2ac4c85d763807648ffdaa90000000223de7ca58210596d7075b68f3e26ad950704188ebfc305c4a3da5ee4ba3aaba6000000040c38c7bfd4b3670748ecff205ad66ef6c837c670c087a3429114ad8698a1a5bd2c44779752568b31bf914dc1a4cdb7e69f00048fa99dac478cbd5040c48d781b000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030581ee1ac27ddf3d4bb1f0d6404fd67ed40e9a8e728eaa78bc1c438d3407e7927d6a49f48a8f07db1170672df19cec71fcb71d97588503150628483943e2a1400000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} \ No newline at end of file +{"proof":"00008b640000045b0000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000029c000000000000000000000000000000000000000000000000000000000000000102569a59ee1ac7a8d3d639e5b0ce3d403b83817fad4ef0ce64ae2befa3e5b9880000000000000000000000000000000000000000000000000000000000000002125c927dd0de76f063cb388b0eb79006a71c2c467d77347c912716e226214d6300000000000000000000000000000000000000000000000000000000000000041bdef12b868de34c7158964699584da32b1e7f038d2db9e86937f4320f0b209b1fe377018287e4433534dd3e41c258ecfb4f45d32c6bc672cfd0207185fde0fe000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000193267463615cd9b4ecaa6f720f5802327eac0b7313912d4f33b80b572fbc14508ba3c9b66832b1f42f21e1fbcca04fe95cc97b2c32a66f24f16e42853993a0e00000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012189e27304c838e300000000000000000000000000000000000000000000000985c06289c30a6a9f000000000000000000000000000000000000000000000009420ce02918efb1880000000000000000000000000000000000000000000000000000f48c23066f5e000000000000000000000000000000000000000000000008f73303fb5521728500000000000000000000000000000000000000000000000441d894a4da4b43270000000000000000000000000000000000000000000000097e112b4dad2e16b80000000000000000000000000000000000000000000000000002d4845277c71d000000000000000000000000000000000000000000000003532fda527bef209b00000000000000000000000000000000000000000000000018fb29dde3adc50c00000000000000000000000000000000000000000000000a3284a388739fc7620000000000000000000000000000000000000000000000000002bcbb9a83ebda0000000000000000000000000000000000000000000000051b88c6a06c0f8d6300000000000000000000000000000000000000000000000d2275b2fb2e01048e00000000000000000000000000000000000000000000000041ea5add096a879e00000000000000000000000000000000000000000000000000022998a28814a800000000000000000000000000000020a4c09b8157a83ede3e933a0c8a17cb0800000000000000000000000000000000000e10b37afd746f69689ef702a863470000000000000000000000000000003bdc6f25064046c31fac6815ad6d834f52000000000000000000000000000000000015532f1394158280e9c5b262495bca000000000000000000000000000000200f5a8c403c3ae98e465ece5d93565808000000000000000000000000000000000001b3d265f330ec060e354e19932941000000000000000000000000000000d9adf8961780b226c47c87476786a04bf200000000000000000000000000000000000741a698ce4d0bc1f593ce7ceece51000000000000000000000000000000a259417e85fda5c9d3a13a85e88c0b5ac9000000000000000000000000000000000011ed0b39603c1b8b252e73385367c0000000000000000000000000000000467158cda2d8a4beabb695c6e7e1672ae30000000000000000000000000000000000142e068301743e86fba4f53335f92200000000000000000000000000000096650cbf350fd79e4e21a3a53f084e5359000000000000000000000000000000000025e86237c45eeb6939f852e4019e10000000000000000000000000000000870ec61adc23bc1294a793de7d329135e300000000000000000000000000000000000d59e4f667228b55d76d57b80cbb4a000000000000000000000000000000dfa123d263c27f5e0a447510bbbf014a24000000000000000000000000000000000014c0e9197abcac09fcca8aa3f56231000000000000000000000000000000693200aaa7a1cf111060bfd9649742812e00000000000000000000000000000000000a64ac6619042e406467e1ef5c7d8000000000000000000000000000000017242d34ae4d5bc824da2a7b879251db3000000000000000000000000000000000001bd2c1cfb5141b0e5a5be4b94e65da00000000000000000000000000000065d868bbcd8b74f45dd8f024f2428cdeca0000000000000000000000000000000000222d34b257386cc9497f829dddaee8000000000000000000000000000000d50105a74dbf09f4818c455b6d7b0fa27000000000000000000000000000000000002abdf5ec09815d6c5bf9f88e0d26fd000000000000000000000000000000d34505e69518c155621b27dea90d44c862000000000000000000000000000000000028e927dd263b5a5eecbab80b4f0ac30000000000000000000000000000003087be9b771666928f848dd7bfc5e957dc000000000000000000000000000000000010bfc3e0fdecef090eb1705d77ec2b000000000000000000000000000000c9e70926e040e8728ad4d1678beeb4670400000000000000000000000000000000002946af12346abfd95caf6699b543a21a3793a9a941b6e4dd953b737235778140fbba9ac9c36b531d371bda74aa1fd6162cbac937efe944dabb0a430f4be0dbe7382dadaff6053e26aad9b97b55e02b16ab9efed44bea0071b2c05a093c31e7252538ed8f53dc730a04cf16b0d55c5c261022d541b8676341ddadb61f9626f05abd6f656ee4e1929e5c303916ae7f3404f11061e011161df0cf1a31e084d3e1c37135d45364d2ab1e39253d689f31b419965fb39c9829702afe0681cb3b58b5a46648d6f17cbe45aee13165b3de25bd1f63ee0ce13aa8e5f2e42b8bf6dddc6abdb38ca12c38a7f90035779fb3560a3402106c22f7743b27312fcd5fa39c0c5ef9393192bda7d86ba51f3fc1ea331f670ae7ab9a7d83a39a1d56b5833afaf6d2486f780a64adb200fd1cedd76e9aa7501c6b958892a372a0d31ee97c25b27585ab615ded56c7b202709bcea02f4ad746029b9c89243932aceb3c6eabc08ed44c4e78ee760e2cebe204bd87a737cf0c100fa6a19b5f300b28e99add95c4db87945001bc77380e632387fc9bf8fb4e75360d1c2e5b00ee6a997b86d6bec1aa58b5db4b8dc4bc1f73ebca7168c3510a57a12cee9edd53478ef81fb7d56355ad2bafa78ef21455a7f43e36b8a7b2b0d7ee0a2bf7ca51c74be0d52657e6f5024b8775ef36292b7e9bda109b817efbcec84dca11c5c3429a6e7988aef74142045258c7e64ac77baf33d46464526342c2def8f51d464bdd9a17f986db9e0912e407c4ebef64aef6ba1f744cabe3b104a02236ba0d27a85b2b04a4136d9671c9aaea77fadb0d8854564f52f52df2dd7baee926d5075458dd715570fe26f268f5221fa866dfbd587d8abb0943cde1554914d3d2d2232660003c75d1e9c4c3c00f72bee367dda32110b8a14dad1858313439fb43ec014be463c31af0bac5b0ce597e94aec7f6705a699712f3eace15164f39b938752a3b86ad3e1da20fdb6fd54c397acb300738a37afe6611c84e2f22d5d54919830259eab18f0ea42f1dab14f042813bd28133a815680798b4442ae3c32cf595140bfe7e793f4ed5678c627740779f3bd5404ff3cc6ec717e181732cafd2e22d6724bbdaf40a45f95640d65ae5da5b4a17dbff2b2bc66b0076f00ab24dc1a6d9aa2bc874886a704b74ff967cd2fd1ad8bb42cae90ab0f79b9e246642e4b7f9ddf10cf2f9e44db39561406b4cba8bd2c86356d024782bfc1976323bd5e4616946631ae25763db7c26ebdf5e4a427835a7966d5d87cb56978d6a92d8873a27e9800a07a29c7f148a82dcb8ad4c2088078769ee20753de841d6e51c27080a9259737d2ffb6e31dd85ea0c8e2f369edc0b37debaf3c08acc8dbb825b7a3bc6206c99560a3257319e4b1803cc5aca51f7a18867333b0a8dd6c743e38da249bfdf6ae587059fd4ec89f4a9d0fce1779e9e9e5206f66b8d8f0b1152d734fc15e313e5824b0aabc25cd1ba5ece0d708c2a9cb2f3974e5e99adc10c9ce5eae4024740cbf85c2bcf74ff536c8f020e992a6627f007a1bf522776d89dc1e1073cf92ff50c1f962ef279021f6f7c6a281d66d0f6507f031c9fc54c4d9d8e1b04b9619f7ac1dbe517bd743e57a03e8e69299e4ef50a9ca13f60d5043c9de40b5c235018cadd07e21f7896d9d17f5ee0ac3babd4006f560a0e123e3d4f51345f80c7a50ec8d2b0d42f4fcdb6ff7e6f365073b38ba45f810eb785ce3b8683da42a8d58e57e6220b8f056833b6e5bcc887d513c9351fbda047a348b816d30442089059716029ece25c26638ec9a41291a49263bc047cb70c3bed2f937e9ffd56509a3b6efd2eb5b56d13fb29a78a0083a85772eda91f76c9d372af4e894cc7c6424a9e5bb95d2408f60f8125a22e746efb0dd5036f9d15a0044b0ce6824d1dce055ff164612182bb77039363e4aa1714cc81cc02818e0d0a05023aa1c6d49a31810bc98a1f418f496a019924b173fcf343b986ed489ab82d7149ac4347ca31815712a9b7470b8950912d4969ae35ad30bdbda3c2578e7a3bf663be902dfb30040da4505b3ec3d7951419b3ac856ddbac7e3c33b5f31379948c59930e7b3e70e19144cc011088abfa231195cc3f057c533d83f0bdbe0d46df6c5f106400a29b354337b178a6cf16c2d52f34b73766e0cda98376dd9eef548a02e6f7dd5739c7ced639fbbf8add45225309dad42e760821bb781540dd9488e7a094a300234d27eeb19335db02f7b35221055e1f0bccfff895ffcb852d42ed5dad249228b01a99c9124e771056b2011699065a6ae251d889b74ebe4c8a081285c05a333772be976242e7794d8ce1292ea02c34ddf89e06afe7fcafacbe3ff380c4c6ac2d8c6f0ebcbeea31b6dcbd8f883c1491a73470cc6ed2a64c85ebf85650c980d6455c4161c0c590e27a00be97ea682dabf2c027be8c392a33e2e0e327117de8baef83c2b16e73e5e564591da163e2295544427ef991ba9eae1d6c4145e9b3a3e9f78d1b2bdac68c1e14e1a661108f1c46723ffd82434bfc32c2a5eefd71d3d30f00fb3ac9e1ea3b2afd555cfd57a72277d571f6f5e15a8104f75f809c350606a6b2675318cde836a924a8c6a2187414f3bef92347292bd3a81b69d955774c112ee996f33235dd028087fb5f56a75d0ee679a841c6a822ef2235e5107f5a1414556bf0d4a67870de5806fb2a35d0370bca02651b89f0fd6ae04e52a5c0bcfdbde8096299a5116d21214839d7ef56a720b6e3b394c9e7c77816bd24b143d9a6f5f5e7f378dcc3c41549d10cdc10a33d21ab96de1843f9729a7e4c6b499b628a2e3c51f1e51855bd0a8623ae1b701cdf0db1c53dc3b3ad63e79efae4826c9a4022b673327a1e5a99a021961e1f9877460b5627961b25b3f1c3beb9da1d00735c5fe3eda62872be3bc1aa7ff0c9caa4b71f00284219ed4e00691cb8d38c4d4e0c699e86479b0ba11fbb4597ac44b34e4700375b434bea848b21b3533f3552d119140224305204b5b89c08ce981c5165c6045a1ba261fd66bac1c7e1f42131262156aa7a52466c9504c3736c10571b6e6319e56ce2f62387fea59df9c9545cf3b8deddfd2d5c4abaf3de7cf08e95889c3426797310c5adb5b12bdf53d8de0b409fb365ec1ad572b41a406e213b3086930b0fd4e837d1aa46aca7faa17b077653c4398253f7c7f6f5d16fb36c314a63087a2501378020b090395c15a36915ee144fdc5eeb1e02b199159baacfafc4b84fa3112d3d8930b50776e5da242f29446de0200bd77dd54ad8a1aa2589e30673029606fd00ea75886a050975bcaec46eb2c5733bb026c5920c05ed28ba4a063135371d912736b053d46439bf9a68ba6eedf941357abc5d878e6e53008c9db59aad5629a06e5ffa90c911f366cba8d2f7104a742b03cb96e8cae8c78c50584e9bc8550fc8fd8e4ac147d101d78390d18c60d1f5f291b554227b48384d1a6300ddca56154d320dd43c82f0ea5aecdc4f176eb5f3d9d87faf33ce9e7e180f991d8f5060095fad700e44198822b0af7978e17599f1e06ea0575e298ead4692ab44a9489b1d8d9bf4436a2b863b88b39d0b9cc8354dc6d0c15e17b402adcaf06ea66be07606234912f0fd32ed8f6a8ea485d30486fe12c80224c4d9aa6831d2e2d9423a6610473387f5624a055835e6a6dccd324d7d5262daca77019febd171497d53652a1180e1c76c53e3dfe126576b8b173f9a545fdacfb6dfac476f2440d8f193bc411be4e0f7351dfd2ec6fd2f8a5421639a49ec4fc6a156c452dbf7045d5477bbca2ab4673d80f6ed21d500f64627a758005179607b119bc057ce0fa0c47eb9094e1b88b5694786e591a5ec7d4dda0f51fd7cd25580483f4d571542930da8cf87150ce769ce7207787e7b11b9a2a9ebc0a449e85d18193662a20a7b06fee8ecd7b22b12e7ef98f6d6b928d4a332c89688f4357bf66d3145918c944a6d9737ce69c20176ac1dd368c287891ccb6ac708383d7e19a4c0bb550b37ef43109c701aaf6b060986e5de4aaa19d55c0f4d2bcb28c8fa2bf8198252cbba7d438005eaadfafb25a3945fd9bbbbc2f733c35b8f52ee47e6328b0c4cfbe1a55892f69504629362107de9c1ea93ce5f6f9fe4ea153a0c34b82468da7ad603fa47300620163fa79f05e65b742f9d108eb8c165a17aa59205146388b4b041f96c820bc049bc12017c194e299b08850a6962d72f86adecf38662c1b887cdc00c630de454cd5e0eadd52cd0543c898dc78c9c41647b1c644aec36905b8b48754ed28c9c1642315d532f13d6a7e246f5ed1a420e648d1420e249ef591db854790f13ff8472e9d5716db2225c3fdc86b1b9ae0f49a737776f663e0961b5a3d097273ea025993f8eddb6ed166524ff7013a9505ab0697ab9656ef8df024288eb0246f3d479b98d49dac14824da7f57e458c9e692792e3665e686a92517fd3d85e8095de86a55545b6bf7280a4a5961688b9976d48667a3eafa29e4ab85e42f73f903cfb282f82fe85a095913b5bfb988aefb5372ead5968301f97473a39827adfc0d639d19b72ec91e2530159cf73c74aa49cbcba799c8142dbc663dad8fad71d871180c640e5c09a48cb60d12539e1f0854a22a7ceadcd92c6757bf81277bfdf73387d93057d0dc17306c294309b187ae6f3b963e6eda567bb25568630739eae17d03a1583fd03a363d8e2f39ef61fd7f473cadf59e34fe571599aa265912d19d36995029ce08eeb0ae5e122c87ad8b0eeb81742015bbaa9b1ad1cde0d314925eb1dfe999f96b9b73f2de2b1df5e24336e7045710dd2a598e8cdc9b4a60fd2e495a386101975cec2b730125c4b612696d968093ef30d7798ff3d89750ee37d27ccff3c165541fdcb71cd92a2b5a8b69a9c7cbbaca4ed8619122b031d01746d98b328d5125c342b3542a1a27b2de2cf6ee19aca504fdbed41b82acfd2e35f9fe21b2cbf48923de49ce94a10308c12fbaf3a006dd8480579aa3dc67fd606d30f8ffb6c72af37a9b975f0d230fa5c900868d929ca5debc440fea04da76707f55aa2711b6c2e705283e62c43e081e4ce2964478cb7a407061331548eedcdc943649de08e219f3735d60245136117b6e4974845c04a553ba17577012ca708c9e0778dc04dd9bde3607b552b2450f8ecee6aae366ebf27daf9e73a7a5ff1f41e1e58859f3516fe506fbc52306422459bc5cb9b5160babe71ed79b8299794d3e84e85043d655cbc0c865048a4bf602b7fdef6eb81cf63d875280a36af50e800b9b2018ac74dcd813ddb556ba55d51e3a1b0484d38bf0b332ea375887c5a9bc4abbfee35f3a2b7036927ec6e4d5700ffcb728d107c93b0463e84f7afaa535eef609f49a1ba9d6b5323fd3c6257ade2486fddef5f12453bda4afdf58af6fa1d87b9604d2ba76dacc0a29e61abdfe3b2f40670d057dd13208d1a8d1fe980868adea0c98bdff8a923df4bfaae14c0f6f04f260b9b8dd86fe2e4bfc5f588fc38afc222cf0681abe5cacf6a8d9d01fea962889a1fc5e40fdd2a2aaa5f28aab864b72471c65744f08df7e4c22bfdfb12e6608caa0510fb51c74047a8e4959794d97d196fd3def2a82f42c18c3e28dc3f0c221017f784c6e9c87374fe2abb69f8dcead7e8f461e3b851e760f985a8fc888991811b2e3460c96f4e57f47fb79eb0126fc3b491dc654a5718e2b76d17f7ccc5a23b6591f7488fd295acfc4af9a0846a0229bbd4a9323920bcef5c39acf8b96940a5e9d3fa3cb770937a86385f956af6596c466fbc8bdd7ce6cb922dad7d5340c0a483fab0a66cc6298833a72e67770e184efe1ea85b84996368100035f8a599927cba10ed7514a95f87c85eff8c2f73031178117c94a5d75b98babdcc77a1e3715cdbd25640175e07f6d48862479306927c96a985ccde9211c899016b9b76312088a3a8d95aad87d74332a765c46c48ec88f964da624744bc1dbc9e5767d5e4a1b03081838cbc541d72daf68c9acc5cdb556b48b9986099525879c96fa54b0071f9c314d017ae49cb966e5e99ac832beee1405a22742c9d92f4923a07dabc88c0771311e26af2c044d4ab793e2e5edf9e23e23702c313f91d9355519e3bcc77e0a17a498f05b63bc72955e597c35603b015bf00fbeb766b7b079d4cc3bccd95321d79afaf7242b08d5d8468e7662453561e87c4cc0add16c4c193abe86b1c84e126c910075b2b11bd5eafbfdb02e4322ea28dbdfeae3e7f80ae1bead12c6c98804387c23debeed15fd9cf14a859c1888e90b606bab746308eee70b77dd5b234e0b6e9ade85584168a385dbfdb666a6d32c4087ab1d8b2d5ac1e9b9c76c2f178927ef87a3fe660fc38511db450e423f69e3af5f287d02ac32ff5ef6be0c37211d101e8b407891319927949adf5fa2187f046d04b7271bfa4c15b679d30d67432204c7018a3bcb0ab57dce794c0dc7aa1a391e085b18ec07956640ec2d2e8535a1223650e1a8595310c152cd6ba4edebf3bc74224c752840d2387a72f7a91b750418eb5053ebbaf44c686f7f1eab04d936010b39e0ab380746925af72f034a94831188b55d60605c1f11d444159c4b6b76ea3a380e8830b2f7510de6a69abd1c7e20fee8b86649318150383b52707d2879b64bea7a78b30f4f038213bdbe4f179b23b4811128cc53717aca1e949ec0db406ac1fd4132ba8a50460c28b2a900adbd03a71aa7a47bed45b42a6ee50ef07fa754f42b83917899cb189628b8ed1c08ce2442f78e792d36c0727579fd95e2761a45e48c1b3152740fa65e676eb45ed2a3184d3b40d9620b53d748bcd365809fa8f1cfb6fadf16f76e21167ba17b61724c13dc78c7eaebdf2b1f7a353b81f198f4614ff9b674540f275ddbdab00a6ad50e00ff3fa0ab62677be7b24d1989d7e491a2d40b541ab31e0f2f845313e6d58133254ec3b7fdc5a657767922b1f95e8e27dd24d98704e9aad298618a666f5b9f001dd453fd334f0efd4474f50afe94f5910e272fa88bd0ef642a52bb32bfcc1bd60d4e9a6643795aa9d3b35569a0bca6a2baa7e4363e54ae7cb2017616d15f2d910515692752df16e4026d00b7de61fb5416581c627c296cf20cbcf7141f7728ab15f5c1cd527ca111e217de87b07fde9e297592e82e446eed82d4ff6eebcd135f148e6ba7491f31f73588d9b19bf480138d96e2c74b8cf69eff55af499b71eabb1bf39091abcd27f00a7d21661d138f66c2def69535bc456099f770030d162c8822a3b5bd1a8d2ae07f3d563f27e4d27a45ac1d9b1e37123ca2d1d538700e747b2a9b41e5c19aee15c5cbcef302f5d4f784943cd709db1d595977e9fd8b217247297df5252225af7e0c8d46c9dbc638e9680a172f8ba923bcfe84f507c234e8da1efa2d9c1a61f0922860bd2bc949f8d94dbbc7ba8268aa4e0d491d31fd9d741c305444e8510cfc7dc53eff164228892196a3316501e45138edd7ccf5499d03ac17473cb8c960910c5662caf159d5b10573c825736a0d3e9538d6e3b0c7ea955f2bdd1c1492ad8cfd0323401ba4eaafd8995421356caa3f7c8da40f6eea88a34f0be976eb318393872322087d8619a822c6ea17494df22619d59ba956986460da2e38f0fa65203a9db98ba0e903286d68b1bf1490aad7bc93921ef3e4b787da2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006aa6080e2e0426a7ab1f68a05c174e8bc01866330086dca2248ab3b3731ff26003949201707b407a0f67de1b95b4fc091bf19111f4437188732ef16eea1a6b6020c4975d1ea76a8e96cb18c92941fa00d0c2efb76803b9112074fbbae2cb9f42b7d8fc760038e2c5c24d2dc10e04404d9f6906a1673de95df84921810a21e5e1d7c23d4c1f5c218388cadf0e8da4c243c6e6ee54340729901d76d32cf1ae17f2e213dd9f61ccf1bf3ff4f5c1790084fe2575704477d346096df1273e5976e84079a5fdb9620f0de62b617ab0bb45aa3e4d87b45632d05ac95ef16a14fa60b27030cca2b7a9e94ba354d03489fdcdfa16d8af1fdcabb53be4112636d7267affc2f1e34508a24318a79fcc433579c97b701496f8c79c1068e198eac96ddf826c60d70c2b305b9f895ccb79ca919329a4299ebbea320cf57d3125a990a4bad9c830d7c7b357ea202fcd10bd9a07dc304c48e48dba2b1e70a653c60a93621192b5c2f22e09d7126391835cb630533690ba9618ddc4e2b6105e3bb929431c1870e781654c43c7885922a4bee8b2bbe7ed296fa2d34e737bc5c1f1d17a10bc652cc980b344f4dd31f25a48b7d45e37e09280c6bb8b17e37715e341f6107d8ef5864731322aee5f839697b7c916d3f321bea17e94fbaee8349c4a75949837fba2805802f9c51a89797ddbf4e9384d68d5cbbc9cdef5dc41af215c74e4ccc22247bda181e8316132a6fc947a533ba66ab3e9a5c6268025eddbe85f15bb9ff853dd9bc012ea3f216a358c4b7e1838484d6f24ccd7192342ffe7e30f7e73b617eada1fe32301e3162a484531d7a44677d4a435ecca0249c3f735f2ecb2b2fd41cee14874a1f49fe2f5f3a20ac51e93e37084ba1f57eeb671dd085ecd319597ee5f66bc5ca11e7a2ca111f5308c3467230c3f0d4ed3e6a25ff171da0289015649ab46f251e0e83c4b37415d77cf92169c4d17008118a0e8fda870bfd2d8d71b706009a277a2fd06ef22bd28770dde752c12c269d771abd22971ec728c24d394b677ad677c0053ae2d18fe754e8537481ac49e2f20ac97fed84fb1fcfa0fa946e7a0086dce7099053a22392bf331f1ce01be8f72a8dbc7d2570b1b2504c1cc3e97a8c0dc04b0039da1f917cb23c7ce9c37d900919eb8c43194d9652fe97e9328436770d6a0f1090b95ec5aae37820ae544c4570ab44fe732c6b59f1839a44dacfd66fb82e511a0387fb4e12908b53de55e1d29eacd588d6b8dff658c804404e27f72a434bbd039887f27d43af85cb8fd572f63cd49f4c2dc49102b4c8be8df393e7d789ba23189bc621566c9f642b0f5714d6bcc141372ce9bd7408762037c4a70925d84bdd298602f3f1015ce659643ac4ab7ec26ba2080dee04413a19fc3dd345e135f0d40857f2874659cfb3bec91bb4d85cc799e16252f39236ca2120d25db8d47c094a0919d2eb4ed07350880b9f887eeb9040882136ed03c33a6870ffe79a8eaf0fb911cde6ecb3f7c468c864b82905376d49dd409996660b85efb7cac1798700eb920645261885277c62b6d9fb29e0a797daec4442071965306fef93e421cb928020243775aa72809864b0d2d68e737eb085fed6744654b4b947ff18017773a9a0710a28ccb0da53d77d181fd0aa3062e35fe65a5ed56cc8ebe57dad940393e025522816b1d1d97fdfa28af6c748d317080b4499409d2efdcf8f1b6273a5f5faff412d190ee38bb1a7924590f2a74d08eac36ca8081589af0b1fea392cf3337474c8107f9a59f56ef65719b1f1521489af9f21d6546b20bedc2e617b3b9d2e3c5dbf03306b320ade8dca97a3110dc761f2faa9843c7aa0c0d92427c64ccb6ba92fdc290bba04878b6274106d6395fc4b24e340dd02a10e01d5acaefde133f93efeff07628206218c2407335307640faba6aa649c216dc6b1fc980ad2856f54068baf1b799de76265cf605c086c49b735ee3b315dd157384dc136cdb6f54e7e0cfcba0000000000000000000000000000006a75c485cf87be4c92744f7df0a2eaeeba000000000000000000000000000000000000f2d07648da4fcd65d82617d173a400000000000000000000000000000038f6bf97c50dd6a375e7cf762fc67c6a0a00000000000000000000000000000000001b93f5f761c9455f73bda5e4edfe900000000000000000000000000000000bf432e3efd16e7ff66f81a2dd12aa730a000000000000000000000000000000000009d05f9292ddf99e80707fadffb0bc000000000000000000000000000000d4e97ed86b6a6fdd1926753b08c2fc638c00000000000000000000000000000000000fe866ac3a6809213c08dc15f11ba9000000000000000000000000000000e0c52820ebc863d2dbcbd777fe77b02c4500000000000000000000000000000000000e3f707fd46be5e0074fbae0989ba2000000000000000000000000000000ac9344428bfb0c9217f7c4626c7b317fc4000000000000000000000000000000000012629e191041c6ea93e5c0aae0f755000000000000000000000000000000d1c0a2db28bc1894e3d8a2d22dc60e8c970000000000000000000000000000000000304c99def73a55ae1c3ebd9d4d7009000000000000000000000000000000e54f6413a82290147564fb057cfa789b0400000000000000000000000000000000002583673b3ecd28404eeef0f8d9d0d4000000000000000000000000000000af6c2adde50398cedf2089031e2291dc520000000000000000000000000000000000056d69be1fb381aedebf7de8bca03200000000000000000000000000000025148637aca922a6e3b3cc79c318b2fd25000000000000000000000000000000000007eb04afb8bf7f6dbe2736f662f337000000000000000000000000000000767769c9f7492f460d4e30d8dd7b8a83c9000000000000000000000000000000000027070450cedd24e4039fa316ca1290000000000000000000000000000000701de0578eb2c6188da4d522c8984b8a6b00000000000000000000000000000000003042027948358066c2e49a4409bb68000000000000000000000000000000f1300b2c2e0a9e10795b044615d88e9438000000000000000000000000000000000003c2ad4b58ddbae60dd4143c765b6600000000000000000000000000000066f9d8176ef2177148bc3baa83462c9a5300000000000000000000000000000000002314f62e871c26d03a4448071ddefa000000000000000000000000000000d2e877f9e3968766f08b068f38c5781082000000000000000000000000000000000026a0de05ed713dd3b67e579d147e23000000000000000000000000000000e6f4695b853d46cda09ceb24719a78376d0000000000000000000000000000000000174665fba01ebaa4e5f0353c8521e5000000000000000000000000000000af8c81347e1d282627d5835d921ccc0511000000000000000000000000000000000011989e4a9332d9d034cab27923d0b9000000000000000000000000000000d6c49d309f441cdfa1d1ba5da2abbb85d3000000000000000000000000000000000011a480e1a0f8140ed9984b83a7facb000000000000000000000000000000204ee3af0f077c1e20afeb1f22ba8dea3b00000000000000000000000000000000001cc114cd66e97fc4fac20ef47bbf03000000000000000000000000000000a5575335ae35f1a417ead6e54b52589431000000000000000000000000000000000023e2c9fc4acbc6a97445fbbbe6dace000000000000000000000000000000b81bcd56f66e1d60048a7abfa2ac63e07100000000000000000000000000000000001909118832ad01e1276d3055672a2700000000000000000000000000000095337ca1eaa682bd5572994e119cc39828000000000000000000000000000000000007006cb1bb8aa584fb992ce1657307000000000000000000000000000000015e035f523f149f2bc71ee1a0604e69280000000000000000000000000000000000269a1c5429d7e738e852d12e5b2b63000000000000000000000000000000226fa99b18cb6d8044c98bc8f6498bab170000000000000000000000000000000000094d10f2d45d21656244c7af981225000000000000000000000000000000c849ade589b7f6238fe559c8931d46554200000000000000000000000000000000002f2adbe2217506a9e84472c243925d00000000000000000000000000000025bd045bd02c5a4da42c9d856ebaa1ffcc000000000000000000000000000000000010fe648f46df182c985146b90d5ee200000000000000000000000000000005e10400efe15441967580ac93a295f4d10000000000000000000000000000000000093ad3274859a19238f1a48fef0f53000000000000000000000000000000969d87a40cb83590c542a52c81c43b311e000000000000000000000000000000000019fd918dd63ef760a7d71120162b80000000000000000000000000000000ddc1368e48261d537fee14e9776d1ffc090000000000000000000000000000000000123b1e637b4057652320d424a224ae000000000000000000000000000000bd0fc4f32ecba6ea917593bd9283672614000000000000000000000000000000000021e8455de8ec340bcae353deaedb4b000000000000000000000000000000e2a0730f81a0faf77795cfd01d431c9a7400000000000000000000000000000000002f4fa7e14edca2efcc49b146a55a3700000000000000000000000000000017560a101e4e62a17b7ba85d76ccd1132e000000000000000000000000000000000018404b2834d98aedf3df71cd08de6f000000000000000000000000000000dec37e48cde642b80c272d4b2417cb112200000000000000000000000000000000002b02b6fa16a8a4e9d049031152a13800000000000000000000000000000069c2ea187fc5527d577e1c0b0421c7af860000000000000000000000000000000000024d712941f81e82492ffa716b23fd000000000000000000000000000000a03b0a28ec2ebdc96ff63d22b1b9546286000000000000000000000000000000000019d47bb2be4d1f474b039769c43daf000000000000000000000000000000648e22ac49d53b073e51099b4e155290ad000000000000000000000000000000000020232516630aea7abd4bf3f59f2f2a000000000000000000000000000000d7b56dae0b6b4fb2ca8dc4c6877388d6c400000000000000000000000000000000000020ae5182691dd99cd00db855bd2d0000000000000000000000000000009065bbf34a82043b945219dda959e9e7e20000000000000000000000000000000000190b95174efda20ee247c51390009700000000000000000000000000000039b3c3a59cbb81dc3e5bd7db84bf37f0f800000000000000000000000000000000001050b9a04b0be3196344f7b3bd5a6d000000000000000000000000000000ede920772a1cf5c75399b3b3ac0fa6e24000000000000000000000000000000000000a762b1f7a0e36cbb858ad616305bc0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000027161cd7d94ba07d570dc05049367c18d5216051070f00266e3d38e5683ab93129387a1590eae334e1d4338dcb8c82ca96fbf7942473b2383002261d8c3c8851ab7869a89bf3a502a8b56f9776cb290c4c9a4ec3e034e9f981a68f89ba5cc1027bc23eb01977528cdefa37841a12e8f22df810b5e95f3ca98869475dd527bf428bedbfc26f5cf9a5df1bdf8432c8a7908bb3612b9bfb0a6befbcb2118235e6c0f78585666f9f1e0442a55f4a57f1f83c02c956b6c917e57ac38036ae38941d3263916eb4c67179ee88a44fcd6b6c98f002f4fe2cdeadd7065f4ed66b3fa6a481d106837378da9b357a9ce58820d8b8bbcb6f66ce661a02bb93f71bc532916b003ac85f048fb3724836b6a024cdaef9166a7adf87ab185d093a0817daf05009320ee862a3af62fd94a74ad64f6fe04c6cc316b36269b45c10aef262194d312cd09675217eb8dc68b2cd141eacf973e9ce7434cca47f6d5c58295b60e7b201c172f084069512ddc88e3ff33c34c5c48f6b26ca233ef89f6d33e1062a156ea86a914e68ee034c8c1554244303975d6786cc9897b44db6c02d44d677a71674a6e1504ce2768010cb18423e55f064448b9cdcd45fe3b8e4b58dfd542d9c5e3d355181c4bd4fe1c6cadece19fd14e76f19451fc60f4e8f8bc6935fc0786ca88e0a3d419bcd8ab0f019655ff3109aaedb49f0e6f0888e99f18da4c799bf905a7d3f9360d5ec93b851acc7ada9510dc383a0dd7f9b9baee59d0e6f0e310b4a3e89b929711f561890ed8ad279dd2bfe648e6ed056c195d1c5d8de9b30cb1c5b13e1783c8029ba89ac82b835f1059e6ed9e47f5f3889c8fde43ca956ae3fcbf319654eaf711d7ef8096e220d644654342dee2bbafe5ead303e17d136e6b010d921b9aa0030abba364f85bde187d35e2587dabf837cd2fd214ac5a93c40153e30857cbc7890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e384122fa6ef39cd678c54b3acf21ccc0800000000000000000000000000000000001fe645c24f836a5f9f2e7f2bfb64c80000000000000000000000000000005aa1afa7f068421f97e7b135bbcc72f72c0000000000000000000000000000000000231051ed83ade2ca091843c6e106ef000000000000000000000000000000a8a5ddd351e975251400bd35e402d946f200000000000000000000000000000000000449a718d48f5adddb0c289bc672a20000000000000000000000000000005912b23ff4f97982c1b6b19081bce393620000000000000000000000000000000000086eec3524f43ea66f02b65c18d4620000029c","publicInputs":"02569a59ee1ac7a8d3d639e5b0ce3d403b83817fad4ef0ce64ae2befa3e5b98800000002125c927dd0de76f063cb388b0eb79006a71c2c467d77347c912716e226214d63000000041bdef12b868de34c7158964699584da32b1e7f038d2db9e86937f4320f0b209b1fe377018287e4433534dd3e41c258ecfb4f45d32c6bc672cfd0207185fde0fe000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000193267463615cd9b4ecaa6f720f5802327eac0b7313912d4f33b80b572fbc14508ba3c9b66832b1f42f21e1fbcca04fe95cc97b2c32a66f24f16e42853993a0e00000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac4f3ee53aedc4865073ae7fb664e7401d10eadbe3bbcc266c35059f14826bb000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"} \ No newline at end of file diff --git a/yarn-project/foundation/src/blob/blob.test.ts b/yarn-project/foundation/src/blob/blob.test.ts index 17ef48656b7..e4a5746ec06 100644 --- a/yarn-project/foundation/src/blob/blob.test.ts +++ b/yarn-project/foundation/src/blob/blob.test.ts @@ -10,6 +10,7 @@ import { Blob } from './index.js'; const { BYTES_PER_BLOB, + FIELD_ELEMENTS_PER_BLOB, blobToKzgCommitment, computeBlobKzgProof, computeKzgProof, @@ -97,4 +98,38 @@ describe('blob', () => { ); expect(isValid).toBe(true); }); + + it('should evaluate full blobs', () => { + // This test ensures that the Blob class correctly matches the c-kzg lib + // The values here are used to test Noir's blob evaluation in noir-projects/noir-protocol-circuits/crates/blob/src/blob.nr -> test_full_blobs + + const blobItems = []; + for (let j = 0; j < 3; j++) { + for (let i = 0; i < FIELD_ELEMENTS_PER_BLOB; i++) { + blobItems[j * FIELD_ELEMENTS_PER_BLOB + i] = new Fr(i + 2); + } + } + const blobItemsHash = poseidon2Hash(blobItems); + const blobs = Blob.getBlobs(blobItems); + blobs.forEach(ourBlob => { + // const ourBlob = new Blob(blobItems.slice(j * FIELD_ELEMENTS_PER_BLOB, (j + 1) * FIELD_ELEMENTS_PER_BLOB), blobItemsHash); + expect(blobItemsHash).toEqual(ourBlob.fieldsHash); + expect(blobToKzgCommitment(ourBlob.data)).toEqual(ourBlob.commitment); + + const z = poseidon2Hash([blobItemsHash, ...ourBlob.commitmentToFields()]); + expect(z).toEqual(ourBlob.challengeZ); + + const res = computeKzgProof(ourBlob.data, ourBlob.challengeZ.toBuffer()); + expect(res[0]).toEqual(ourBlob.proof); + expect(res[1]).toEqual(ourBlob.evaluationY); + + const isValid = verifyKzgProof( + ourBlob.commitment, + ourBlob.challengeZ.toBuffer(), + ourBlob.evaluationY, + ourBlob.proof, + ); + expect(isValid).toBe(true); + }); + }); }); diff --git a/yarn-project/foundation/src/blob/index.ts b/yarn-project/foundation/src/blob/index.ts index 6912a4554ae..2080810a107 100644 --- a/yarn-project/foundation/src/blob/index.ts +++ b/yarn-project/foundation/src/blob/index.ts @@ -52,6 +52,10 @@ export class Blob { constructor( /** All fields to be broadcast in the blob. */ fields: Fr[], + /** If we want to broadcast more fields than fit into a blob, we hash those and used it as the fieldsHash across all blobs. + * This is much simpler and cheaper in the circuit to do, but MUST BE CHECKED before injecting here. + */ + multiBlobFieldsHash?: Fr, ) { if (fields.length > FIELD_ELEMENTS_PER_BLOB) { throw new Error( @@ -60,7 +64,7 @@ export class Blob { } this.data = Buffer.concat([serializeToBuffer(fields)], BYTES_PER_BLOB); // This matches the output of SpongeBlob.squeeze() in the blob circuit - this.fieldsHash = poseidon2Hash(fields); + this.fieldsHash = multiBlobFieldsHash ? multiBlobFieldsHash : poseidon2Hash(fields); this.commitment = Buffer.from(blobToKzgCommitment(this.data)); this.challengeZ = poseidon2Hash([this.fieldsHash, ...this.commitmentToFields()]); const res = computeKzgProof(this.data, this.challengeZ.toBuffer()); @@ -76,17 +80,15 @@ export class Blob { return [new Fr(this.commitment.subarray(0, 31)), new Fr(this.commitment.subarray(31, 48))]; } - // Returns ethereum's blob hash WITHOUT the prefixed version - // We use this in the circuit since it can fit in a field. - getEthBlobHash(): Buffer { + // Returns ethereum's versioned blob hash, following kzg_to_versioned_hash: https://eips.ethereum.org/EIPS/eip-4844#helpers + getEthVersionedBlobHash(): Buffer { const hash = sha256(this.commitment); - hash[0] = 0; + hash[0] = VERSIONED_HASH_VERSION_KZG; return hash; } - // Returns ethereum's versioned blob hash, following kzg_to_versioned_hash: https://eips.ethereum.org/EIPS/eip-4844#helpers - getEthVersionedBlobHash(): Buffer { - const hash = this.getEthBlobHash(); + static getEthVersionedBlobHash(commitment: Buffer): Buffer { + const hash = sha256(commitment); hash[0] = VERSIONED_HASH_VERSION_KZG; return hash; } @@ -109,10 +111,42 @@ export class Blob { return `0x${buf.toString('hex')}`; } + static getEthBlobEvaluationInputs(blobs: Blob[]): `0x${string}` { + let buf = Buffer.alloc(0); + blobs.forEach(blob => { + buf = Buffer.concat([ + buf, + blob.getEthVersionedBlobHash(), + blob.challengeZ.toBuffer(), + blob.evaluationY, + blob.commitment, + blob.proof, + ]); + }); + // For multiple blobs, we prefix the number of blobs: + const lenBuf = Buffer.alloc(1); + lenBuf.writeUint8(blobs.length); + buf = Buffer.concat([lenBuf, buf]); + return `0x${buf.toString('hex')}`; + } + static getViemKzgInstance() { return { blobToKzgCommitment: cKzg.blobToKzgCommitment, computeBlobKzgProof: cKzg.computeBlobKzgProof, }; } + + // Returns as many blobs as we require to broadcast the given fields + // Assumes we share the fields hash between all blobs + static getBlobs(fields: Fr[]): Blob[] { + const numBlobs = Math.max(Math.ceil(fields.length / FIELD_ELEMENTS_PER_BLOB), 1); + const multiBlobFieldsHash = poseidon2Hash(fields); + const res = []; + for (let i = 0; i < numBlobs; i++) { + const end = fields.length < (i + 1) * FIELD_ELEMENTS_PER_BLOB ? fields.length : (i + 1) * FIELD_ELEMENTS_PER_BLOB; + res.push(new Blob(fields.slice(i * FIELD_ELEMENTS_PER_BLOB, end), multiBlobFieldsHash)); + } + return res; + } } 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 1d6561e2581..4d89572b722 100644 --- a/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts +++ b/yarn-project/noir-protocol-circuits-types/src/type_conversion.ts @@ -7,9 +7,11 @@ import { type AvmCircuitPublicInputs, type AvmProofData, AztecAddress, + BLOBS_PER_BLOCK, BaseOrMergeRollupPublicInputs, type BaseParityInputs, BlobPublicInputs, + BlockBlobPublicInputs, type BlockMergeRollupInputs, BlockRootOrBlockMergePublicInputs, type BlockRootRollupInputs, @@ -166,7 +168,9 @@ import type { BaseOrMergeRollupPublicInputs as BaseOrMergeRollupPublicInputsNoir, BaseParityInputs as BaseParityInputsNoir, BigNum, + BlobCommitment as BlobCommitmentNoir, BlobPublicInputs as BlobPublicInputsNoir, + BlockBlobPublicInputs as BlockBlobPublicInputsNoir, BlockMergeRollupInputs as BlockMergeRollupInputsNoir, BlockRootOrBlockMergePublicInputs as BlockRootOrBlockMergePublicInputsNoir, BlockRootRollupInputs as BlockRootRollupInputsNoir, @@ -2081,6 +2085,17 @@ export function mapSpongeBlobFromNoir(spongeBlob: SpongeBlobNoir): SpongeBlob { ); } +/** + * Maps blob commitment to noir. + * @param commitment - The circuits.js commitment. + * @returns The noir commitment. + */ +export function mapBlobCommitmentToNoir(commitment: [Fr, Fr]): BlobCommitmentNoir { + return { + inner: mapTuple(commitment, mapFieldToNoir), + }; +} + /** * Maps blob public inputs to noir. * @param blobPublicInputs - The circuits.js blob public inputs. @@ -2090,7 +2105,7 @@ export function mapBlobPublicInputsToNoir(blobPublicInputs: BlobPublicInputs): B return { z: mapFieldToNoir(blobPublicInputs.z), y: mapBLS12BigNumToNoir(blobPublicInputs.y), - kzg_commitment: mapTuple(blobPublicInputs.kzgCommitment, mapFieldToNoir), + kzg_commitment: mapBlobCommitmentToNoir(blobPublicInputs.kzgCommitment), }; } @@ -2103,7 +2118,33 @@ export function mapBlobPublicInputsFromNoir(blobPublicInputs: BlobPublicInputsNo return new BlobPublicInputs( mapFieldFromNoir(blobPublicInputs.z), mapBLS12BigNumFromNoir(blobPublicInputs.y), - mapTupleFromNoir(blobPublicInputs.kzg_commitment, 2, mapFieldFromNoir), + mapTupleFromNoir(blobPublicInputs.kzg_commitment.inner, 2, mapFieldFromNoir), + ); +} + +/** + * Maps block blob public inputs to noir. + * @param blockBlobPublicInputs - The circuits.js block blob public inputs. + * @returns The noir block blob public inputs. + */ +export function mapBlockBlobPublicInputsToNoir( + blockBlobPublicInputs: BlockBlobPublicInputs, +): BlockBlobPublicInputsNoir { + return { + inner: mapTuple(blockBlobPublicInputs.inner, mapBlobPublicInputsToNoir), + }; +} + +/** + * Maps block blob public inputs from noir. + * @param blockBlobPublicInputs - The noir block blob public inputs. + * @returns The circuits.js block blob public inputs. + */ +export function mapBlockBlobPublicInputsFromNoir( + blockBlobPublicInputs: BlockBlobPublicInputsNoir, +): BlockBlobPublicInputs { + return new BlockBlobPublicInputs( + mapTupleFromNoir(blockBlobPublicInputs.inner, BLOBS_PER_BLOCK, mapBlobPublicInputsFromNoir), ); } @@ -2176,7 +2217,7 @@ export function mapBlockRootOrBlockMergePublicInputsToNoir( vk_tree_root: mapFieldToNoir(blockRootOrBlockMergePublicInputs.vkTreeRoot), protocol_contract_tree_root: mapFieldToNoir(blockRootOrBlockMergePublicInputs.protocolContractTreeRoot), prover_id: mapFieldToNoir(blockRootOrBlockMergePublicInputs.proverId), - blob_public_inputs: mapTuple(blockRootOrBlockMergePublicInputs.blobPublicInputs, mapBlobPublicInputsToNoir), + blob_public_inputs: mapTuple(blockRootOrBlockMergePublicInputs.blobPublicInputs, mapBlockBlobPublicInputsToNoir), }; } @@ -2298,7 +2339,7 @@ export function mapBlockRootOrBlockMergePublicInputsFromNoir( mapTupleFromNoir( blockRootOrBlockMergePublicInputs.blob_public_inputs, AZTEC_MAX_EPOCH_DURATION, - mapBlobPublicInputsFromNoir, + mapBlockBlobPublicInputsFromNoir, ), ); } @@ -2400,9 +2441,9 @@ export function mapBlockRootRollupInputsToNoir(rootRollupInputs: BlockRootRollup previous_block_hash: mapFieldToNoir(rootRollupInputs.previousBlockHash), prover_id: mapFieldToNoir(rootRollupInputs.proverId), // @ts-expect-error - below line gives error 'Type instantiation is excessively deep and possibly infinite. ts(2589)' - blob_fields: mapTuple(rootRollupInputs.blobFields, mapFieldToNoir), - blob_commitment: mapTuple(rootRollupInputs.blobCommitment, mapFieldToNoir), - blob_hash: mapFieldToNoir(rootRollupInputs.blobHash), + blobs_fields: mapTuple(rootRollupInputs.blobFields, mapFieldToNoir), + blob_commitments: mapTuple(rootRollupInputs.blobCommitments, mapBlobCommitmentToNoir), + blobs_hash: mapFieldToNoir(rootRollupInputs.blobsHash), }; } @@ -2481,7 +2522,11 @@ export function mapRootRollupPublicInputsFromNoir( mapFieldFromNoir(rootRollupPublicInputs.vk_tree_root), mapFieldFromNoir(rootRollupPublicInputs.protocol_contract_tree_root), mapFieldFromNoir(rootRollupPublicInputs.prover_id), - mapTupleFromNoir(rootRollupPublicInputs.blob_public_inputs, AZTEC_MAX_EPOCH_DURATION, mapBlobPublicInputsFromNoir), + mapTupleFromNoir( + rootRollupPublicInputs.blob_public_inputs, + AZTEC_MAX_EPOCH_DURATION, + mapBlockBlobPublicInputsFromNoir, + ), ); } @@ -2535,7 +2580,7 @@ export function mapHeaderFromNoir(header: HeaderNoir): Header { export function mapContentCommitmentToNoir(contentCommitment: ContentCommitment): ContentCommitmentNoir { return { num_txs: mapFieldToNoir(contentCommitment.numTxs), - blob_hash: mapSha256HashToNoir(contentCommitment.blobHash), + blobs_hash: mapSha256HashToNoir(contentCommitment.blobsHash), in_hash: mapSha256HashToNoir(contentCommitment.inHash), out_hash: mapSha256HashToNoir(contentCommitment.outHash), }; @@ -2548,7 +2593,7 @@ export function mapContentCommitmentToNoir(contentCommitment: ContentCommitment) export function mapContentCommitmentFromNoir(contentCommitment: ContentCommitmentNoir): ContentCommitment { return new ContentCommitment( mapFieldFromNoir(contentCommitment.num_txs), - mapSha256HashFromNoir(contentCommitment.blob_hash), + mapSha256HashFromNoir(contentCommitment.blobs_hash), mapSha256HashFromNoir(contentCommitment.in_hash), mapSha256HashFromNoir(contentCommitment.out_hash), ); diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index 91143d08894..50cb73ec066 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -52,9 +52,8 @@ import { type VerificationKeyAsFields, } from '@aztec/circuits.js'; import { assertPermutation, makeTuple } from '@aztec/foundation/array'; -import { Blob } from '@aztec/foundation/blob'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { sha256, sha256Trunc } from '@aztec/foundation/crypto'; +import { sha256Trunc } from '@aztec/foundation/crypto'; import { type DebugLogger } from '@aztec/foundation/log'; import { type Tuple, assertLength, toFriendlyJSON } from '@aztec/foundation/serialize'; import { computeUnbalancedMerkleRoot } from '@aztec/foundation/trees'; @@ -226,9 +225,7 @@ export function buildHeaderFromCircuitOutputs( updatedL1ToL2TreeSnapshot: AppendOnlyTreeSnapshot, logger?: DebugLogger, ) { - const blobHash = sha256(rootRollupOutputs.blobPublicInputs[0].commitmentToBuffer()); - // NB the truncation for blob hash differs from sha256Trunc, because we follow eth's blob hash rules: - blobHash[0] = 0; + const blobHash = rootRollupOutputs.blobPublicInputs[0].getBlobsHash(); const contentCommitment = new ContentCommitment( new Fr(previousMergeData[0].numTxs + previousMergeData[1].numTxs), blobHash, @@ -282,7 +279,7 @@ export async function buildHeaderFromTxEffects( const parityShaRoot = new MerkleTreeCalculator(parityHeight, Fr.ZERO.toBuffer(), hasher).computeTreeRoot( l1ToL2Messages.map(msg => msg.toBuffer()), ); - const blobHash = new Blob(body.toBlobFields()).getEthBlobHash(); + const blobHash = body.getBlobsHash(); const contentCommitment = new ContentCommitment( new Fr(body.numberOfTxsIncludingPadded), blobHash, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 290dbd035e1..6acb7833e52 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -17,6 +17,7 @@ import { type CircuitName } from '@aztec/circuit-types/stats'; import { AVM_PROOF_LENGTH_IN_FIELDS, AVM_VERIFICATION_KEY_LENGTH_IN_FIELDS, + BLOBS_PER_BLOCK, type BaseOrMergeRollupPublicInputs, BaseParityInputs, type BaseRollupHints, @@ -45,6 +46,7 @@ import { import { makeTuple } from '@aztec/foundation/array'; import { Blob } from '@aztec/foundation/blob'; import { padArrayEnd } from '@aztec/foundation/collection'; +import { sha256ToField } from '@aztec/foundation/crypto'; import { AbortError } from '@aztec/foundation/error'; import { createDebugLogger } from '@aztec/foundation/log'; import { promiseWithResolvers } from '@aztec/foundation/promise'; @@ -864,10 +866,11 @@ export class ProvingOrchestrator implements EpochProver { const blobFields = this.extractTxEffects(provingState) .map(tx => tx.toBlobFields()) .flat(); - const blob = new Blob(blobFields); + const blobs = Blob.getBlobs(blobFields); + const blobsHash = sha256ToField(blobs.map(b => b.getEthVersionedBlobHash())); logger.debug( - `Enqueuing block root rollup for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs`, + `Enqueuing block root rollup for block ${provingState.blockNumber} with ${provingState.newL1ToL2Messages.length} l1 to l2 msgs and ${blobs.length} blobs.`, ); const previousRollupData: BlockRootRollupInputs['previousRollupData'] = makeTuple(2, i => @@ -888,10 +891,13 @@ export class ProvingOrchestrator implements EpochProver { newArchiveSiblingPath: provingState.archiveTreeRootSiblingPath, previousBlockHash: provingState.previousBlockHash, proverId: this.proverId, - // @ts-expect-error - below line gives error 'Type instantiation is excessively deep and possibly infinite. ts(2589)' - blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB), - blobCommitment: blob.commitmentToFields(), - blobHash: Fr.fromBuffer(blob.getEthBlobHash()), + blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB * BLOBS_PER_BLOCK), + blobCommitments: padArrayEnd( + blobs.map(b => b.commitmentToFields()), + [Fr.ZERO, Fr.ZERO], + BLOBS_PER_BLOCK, + ), + blobsHash: blobsHash, }); this.deferredProving( @@ -917,15 +923,16 @@ export class ProvingOrchestrator implements EpochProver { provingState.blockRootRollupPublicInputs = result.inputs; provingState.finalProof = result.proof.binaryProof; const blobOutputs = result.inputs.blobPublicInputs[0]; - - if (!blobOutputs.equals(BlobPublicInputs.fromBlob(blob))) { - throw new Error( - `Rollup circuits produced mismatched blob evaluation: - z: ${blobOutputs.z} == ${blob.challengeZ}, - y: ${blobOutputs.y.toString(16)} == ${blob.evaluationY.toString('hex')}, - C: ${blobOutputs.kzgCommitment} == ${blob.commitmentToFields()}`, - ); - } + blobOutputs.inner.forEach((blobOutput, i) => { + if (!blobOutput.isEmpty() && !blobOutput.equals(BlobPublicInputs.fromBlob(blobs[i]))) { + throw new Error( + `Rollup circuits produced mismatched blob evaluation: + z: ${blobOutput.z} == ${blobs[i].challengeZ}, + y: ${blobOutput.y.toString(16)} == ${blobs[i].evaluationY.toString('hex')}, + C: ${blobOutput.kzgCommitment} == ${blobs[i].commitmentToFields()}`, + ); + } + }); logger.debug(`Completed proof for block root rollup for ${provingState.block?.number}`); // validatePartialState(result.inputs.end, tx.treeSnapshots); // TODO(palla/prover) diff --git a/yarn-project/sequencer-client/src/block_builder/light.test.ts b/yarn-project/sequencer-client/src/block_builder/light.test.ts index 3332a311742..0927f3e95ca 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.test.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.test.ts @@ -11,9 +11,10 @@ import { makeBloatedProcessedTx } from '@aztec/circuit-types/test'; import { AZTEC_MAX_EPOCH_DURATION, type AppendOnlyTreeSnapshot, + BLOBS_PER_BLOCK, type BaseOrMergeRollupPublicInputs, BaseParityInputs, - BlobPublicInputs, + BlockBlobPublicInputs, BlockRootOrBlockMergePublicInputs, BlockRootRollupInputs, EthAddress, @@ -333,7 +334,8 @@ describe('LightBlockBuilder', () => { const previousBlockHashLeafIndex = BigInt(startArchiveSnapshot.nextAvailableLeafIndex - 1); const previousBlockHash = (await expectsFork.getLeafValue(MerkleTreeId.ARCHIVE, previousBlockHashLeafIndex))!; const blobFields = txs.map(tx => tx.txEffect.toBlobFields()).flat(); - const blob = new Blob(blobFields); + const blobs = Blob.getBlobs(blobFields); + const blobsHash = sha256ToField(blobs.map(b => b.getEthVersionedBlobHash())); const rootParityVk = ProtocolCircuitVks['RootParityArtifact'].keyAsFields; const rootParityVkWitness = getVkMembershipWitness(rootParityVk); @@ -354,10 +356,13 @@ describe('LightBlockBuilder', () => { newArchiveSiblingPath, previousBlockHash, proverId: Fr.ZERO, - // @ts-expect-error - below line gives error 'Type instantiation is excessively deep and possibly infinite. ts(2589)' - blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB), - blobCommitment: blob.commitmentToFields(), - blobHash: Fr.fromBuffer(blob.getEthBlobHash()), + blobFields: padArrayEnd(blobFields, Fr.ZERO, FIELDS_PER_BLOB * BLOBS_PER_BLOCK), + blobCommitments: padArrayEnd( + blobs.map(b => b.commitmentToFields()), + [Fr.ZERO, Fr.ZERO], + BLOBS_PER_BLOCK, + ), + blobsHash, }); // TODO(Miranda): the wasm simulator can't run block root due to the bignum-based blob lib (stack too deep). @@ -378,7 +383,7 @@ describe('LightBlockBuilder', () => { ), ]; - const blobPublicInputs = [BlobPublicInputs.fromBlob(blob)]; + const blobPublicInputs = [BlockBlobPublicInputs.fromBlobs(blobs)]; const outputs = new BlockRootOrBlockMergePublicInputs( inputs.startArchiveSnapshot, newArchiveSnapshot, @@ -394,7 +399,7 @@ describe('LightBlockBuilder', () => { rollupLeft.baseOrMergeRollupPublicInputs.constants.vkTreeRoot, rollupLeft.baseOrMergeRollupPublicInputs.constants.protocolContractTreeRoot, inputs.proverId, - padArrayEnd(blobPublicInputs, BlobPublicInputs.empty(), AZTEC_MAX_EPOCH_DURATION), + padArrayEnd(blobPublicInputs, BlockBlobPublicInputs.empty(), AZTEC_MAX_EPOCH_DURATION), ); return outputs; diff --git a/yarn-project/sequencer-client/src/block_builder/light.ts b/yarn-project/sequencer-client/src/block_builder/light.ts index b25b0b3a1d0..2bedc856da7 100644 --- a/yarn-project/sequencer-client/src/block_builder/light.ts +++ b/yarn-project/sequencer-client/src/block_builder/light.ts @@ -27,7 +27,7 @@ export class LightweightBlockBuilder implements BlockBuilder { private globalVariables?: GlobalVariables; private l1ToL2Messages?: Fr[]; - private readonly txs: ProcessedTx[] = []; + private txs: ProcessedTx[] = []; private readonly logger = createDebugLogger('aztec:sequencer-client:block_builder_light'); @@ -37,6 +37,9 @@ export class LightweightBlockBuilder implements BlockBuilder { this.logger.verbose('Starting new block', { globalVariables, l1ToL2Messages }); this.globalVariables = globalVariables; this.l1ToL2Messages = padArrayEnd(l1ToL2Messages, Fr.ZERO, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP); + this.txs = []; + this.numTxs = 0; + this.spongeBlobState = undefined; // Update L1 to L2 tree await this.db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, this.l1ToL2Messages!); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts index dfa62f443f7..5ca140d2692 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.test.ts @@ -140,9 +140,9 @@ describe('L1Publisher', () => { expect(result).toEqual(true); - const blob = new Blob(l2Block.body.toBlobFields()); + const blobs = Blob.getBlobs(l2Block.body.toBlobFields()); - const blobInput = blob.getEthBlobEvaluationInputs(); + const blobInput = Blob.getEthBlobEvaluationInputs(blobs); const args = [ `0x${header.toString('hex')}`, @@ -165,7 +165,7 @@ describe('L1Publisher', () => { data, account, to: rollupContract.address, - blobs: [blob.data], + blobs: blobs.map(blob => blob.data), kzg, maxFeePerBlobGas: 10000000000n, }); diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts index 7ada1cfd9c9..08939154d56 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher.ts @@ -109,8 +109,8 @@ type L1ProcessArgs = { blockHash: Buffer; /** L2 block body. TODO(#9101): Remove block body once we can extract blobs. */ body: Buffer; - /** L2 block blob containing all tx effects. */ - blob: Blob; + /** L2 block blobs containing all tx effects. */ + blobs: Blob[]; /** L2 block tx hashes */ txHashes: TxHash[]; /** Attestations */ @@ -356,7 +356,7 @@ export class L1Publisher { formattedSignatures, `0x${attestationData.digest.toString('hex')}`, ts, - `0x${header.contentCommitment.blobHash.toString('hex')}`, + `0x${header.contentCommitment.blobsHash.toString('hex')}`, flags, ] as const; @@ -483,7 +483,7 @@ export class L1Publisher { archive: block.archive.root.toBuffer(), blockHash: block.header.hash().toBuffer(), body: block.body.toBuffer(), - blob: new Blob(block.body.toBlobFields()), + blobs: Blob.getBlobs(block.body.toBlobFields()), attestations, txHashes: txHashes ?? [], }; @@ -765,7 +765,7 @@ export class L1Publisher { attestations, // TODO(#9101): Extract blobs from beacon chain => calldata will only contain what's needed to verify blob and body input can be removed `0x${encodedData.body.toString('hex')}`, - encodedData.blob.getEthBlobEvaluationInputs(), + Blob.getEthBlobEvaluationInputs(encodedData.blobs), ] as const; return { args, gasGuesstimate }; @@ -793,7 +793,10 @@ export class L1Publisher { ? args.publicInputs.fees[i / 2].recipient.toField().toString() : args.publicInputs.fees[(i - 1) / 2].value.toString(), ), - `0x${serializeToBuffer(args.proof.extractAggregationObject()).toString('hex')}`, + `0x${args.publicInputs.blobPublicInputs + .filter((_, i) => i < args.toBlock - args.fromBlock + 1) + .map(b => b.toString()) + .join(``)}${serializeToBuffer(args.proof.extractAggregationObject()).toString('hex')}`, ] as const; } @@ -819,7 +822,7 @@ export class L1Publisher { data, account: this.account, to: this.rollupContract.address, - blobs: [encodedData.blob.data], + blobs: encodedData.blobs.map(b => b.data), kzg, maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS }), @@ -863,7 +866,7 @@ export class L1Publisher { data, account: this.account, to: this.rollupContract.address, - blobs: [encodedData.blob.data], + blobs: encodedData.blobs.map(b => b.data), kzg, maxFeePerBlobGas: 10000000000n, //This is 10 gwei, taken from DEFAULT_MAX_FEE_PER_GAS }),