From b1cfb0020631d81bb8a9a901ba471456144b8561 Mon Sep 17 00:00:00 2001 From: Giulio Date: Mon, 29 Nov 2021 12:59:40 +0100 Subject: [PATCH 1/7] solidity implementation for ics23 Code is splitted in 4 different libraries, following the layout of functions and files of the go implementation - Ops -> go/ops.go - Proof -> go/proof.go - Compress -> go/compress.go - Ics23 -> go/ics23.go Missing parts of the current implementation: - sha512 hash option: solidity does not have built-in function for this hash. A solidity implementation would be utterly inefficient and very costly (gas-wise) - compress functions: this implementation is meant be used for verification, not for proof generation - ProofSpec for tendermint and iavl definition: again, this implementation is just to verify, not to generate - Decompress functions are present but not working: currently investigating a potention buf in the protobuf runtime - Batch verification functions are temporarily disabled due to above --- sol/.gitattributes | 2 + sol/.gitignore | 6 + sol/brownie-config.yaml | 3 + sol/contracts/GoogleProtobufAny.sol | 281 ++ sol/contracts/Migrations.sol | 19 + sol/contracts/ProtoBufRuntime.sol | 2990 +++++++++++++++ sol/contracts/ics23.sol | 107 + sol/contracts/ics23Compress.sol | 67 + sol/contracts/ics23Ops.sol | 166 + sol/contracts/ics23Proof.sol | 229 ++ sol/contracts/proofs.sol | 5501 +++++++++++++++++++++++++++ sol/package-lock.json | 680 ++++ sol/tests/convert.py | 51 + sol/tests/helpers.py | 34 + sol/tests/specs.py | 12 + sol/tests/test_ics23compress.py | 37 + sol/tests/test_ics23ops.py | 62 + sol/tests/test_ics23proof.py | 35 + sol/tests/test_ics23vectors.py | 47 + 19 files changed, 10329 insertions(+) create mode 100644 sol/.gitattributes create mode 100644 sol/.gitignore create mode 100644 sol/brownie-config.yaml create mode 100644 sol/contracts/GoogleProtobufAny.sol create mode 100644 sol/contracts/Migrations.sol create mode 100644 sol/contracts/ProtoBufRuntime.sol create mode 100644 sol/contracts/ics23.sol create mode 100644 sol/contracts/ics23Compress.sol create mode 100644 sol/contracts/ics23Ops.sol create mode 100644 sol/contracts/ics23Proof.sol create mode 100644 sol/contracts/proofs.sol create mode 100644 sol/package-lock.json create mode 100644 sol/tests/convert.py create mode 100644 sol/tests/helpers.py create mode 100644 sol/tests/specs.py create mode 100644 sol/tests/test_ics23compress.py create mode 100644 sol/tests/test_ics23ops.py create mode 100644 sol/tests/test_ics23proof.py create mode 100644 sol/tests/test_ics23vectors.py diff --git a/sol/.gitattributes b/sol/.gitattributes new file mode 100644 index 00000000..adb20fe2 --- /dev/null +++ b/sol/.gitattributes @@ -0,0 +1,2 @@ +*.sol linguist-language=Solidity +*.vy linguist-language=Python diff --git a/sol/.gitignore b/sol/.gitignore new file mode 100644 index 00000000..898188a7 --- /dev/null +++ b/sol/.gitignore @@ -0,0 +1,6 @@ +__pycache__ +.env +.history +.hypothesis/ +build/ +reports/ diff --git a/sol/brownie-config.yaml b/sol/brownie-config.yaml new file mode 100644 index 00000000..984fb758 --- /dev/null +++ b/sol/brownie-config.yaml @@ -0,0 +1,3 @@ +dependencies: + - OpenZeppelin/openzeppelin-contracts@4.2.0 + - GNSPS/solidity-bytes-utils@0.8.0 diff --git a/sol/contracts/GoogleProtobufAny.sol b/sol/contracts/GoogleProtobufAny.sol new file mode 100644 index 00000000..8de3260e --- /dev/null +++ b/sol/contracts/GoogleProtobufAny.sol @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; +import "./ProtoBufRuntime.sol"; + +library GoogleProtobufAny { + + + //struct definition + struct Data { + string type_url; + bytes value; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_type_url(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_type_url( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (string memory x, uint256 sz) = ProtoBufRuntime._decode_string(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.type_url = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.value = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_string(r.type_url, pointer, bs); + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(bytes(r.type_url).length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + return e; + } + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.type_url = input.type_url; + output.value = input.value; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library Any diff --git a/sol/contracts/Migrations.sol b/sol/contracts/Migrations.sol new file mode 100644 index 00000000..922fc7fb --- /dev/null +++ b/sol/contracts/Migrations.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +contract Migrations { + address public owner; + uint public last_completed_migration; + + modifier restricted() { + if (msg.sender == owner) _; + } + + constructor() public { + owner = msg.sender; + } + + function setCompleted(uint completed) public restricted { + last_completed_migration = completed; + } +} diff --git a/sol/contracts/ProtoBufRuntime.sol b/sol/contracts/ProtoBufRuntime.sol new file mode 100644 index 00000000..43a86d44 --- /dev/null +++ b/sol/contracts/ProtoBufRuntime.sol @@ -0,0 +1,2990 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + + +/** + * @title Runtime library for ProtoBuf serialization and/or deserialization. + * All ProtoBuf generated code will use this library. + */ +library ProtoBufRuntime { + // Types defined in ProtoBuf + enum WireType { Varint, Fixed64, LengthDelim, StartGroup, EndGroup, Fixed32 } + // Constants for bytes calculation + uint256 constant WORD_LENGTH = 32; + uint256 constant HEADER_SIZE_LENGTH_IN_BYTES = 4; + uint256 constant BYTE_SIZE = 8; + uint256 constant REMAINING_LENGTH = WORD_LENGTH - HEADER_SIZE_LENGTH_IN_BYTES; + string constant OVERFLOW_MESSAGE = "length overflow"; + + //Storages + /** + * @dev Encode to storage location using assembly to save storage space. + * @param location The location of storage + * @param encoded The encoded ProtoBuf bytes + */ + function encodeStorage(bytes storage location, bytes memory encoded) + internal + { + /** + * This code use the first four bytes as size, + * and then put the rest of `encoded` bytes. + */ + uint256 length = encoded.length; + uint256 firstWord; + uint256 wordLength = WORD_LENGTH; + uint256 remainingLength = REMAINING_LENGTH; + + assembly { + firstWord := mload(add(encoded, wordLength)) + } + firstWord = + (firstWord >> (BYTE_SIZE * HEADER_SIZE_LENGTH_IN_BYTES)) | + (length << (BYTE_SIZE * REMAINING_LENGTH)); + + assembly { + sstore(location.slot, firstWord) + } + + if (length > REMAINING_LENGTH) { + length -= REMAINING_LENGTH; + for (uint256 i = 0; i < ceil(length, WORD_LENGTH); i++) { + assembly { + let offset := add(mul(i, wordLength), remainingLength) + let slotIndex := add(i, 1) + sstore( + add(location.slot, slotIndex), + mload(add(add(encoded, wordLength), offset)) + ) + } + } + } + } + + /** + * @dev Decode storage location using assembly using the format in `encodeStorage`. + * @param location The location of storage + * @return The encoded bytes + */ + function decodeStorage(bytes storage location) + internal + view + returns (bytes memory) + { + /** + * This code is to decode the first four bytes as size, + * and then decode the rest using the decoded size. + */ + uint256 firstWord; + uint256 remainingLength = REMAINING_LENGTH; + uint256 wordLength = WORD_LENGTH; + + assembly { + firstWord := sload(location.slot) + } + + uint256 length = firstWord >> (BYTE_SIZE * REMAINING_LENGTH); + bytes memory encoded = new bytes(length); + + assembly { + mstore(add(encoded, remainingLength), firstWord) + } + + if (length > REMAINING_LENGTH) { + length -= REMAINING_LENGTH; + for (uint256 i = 0; i < ceil(length, WORD_LENGTH); i++) { + assembly { + let offset := add(mul(i, wordLength), remainingLength) + let slotIndex := add(i, 1) + mstore( + add(add(encoded, wordLength), offset), + sload(add(location.slot, slotIndex)) + ) + } + } + } + return encoded; + } + + /** + * @dev Fast memory copy of bytes using assembly. + * @param src The source memory address + * @param dest The destination memory address + * @param len The length of bytes to copy + */ + function copyBytes(uint256 src, uint256 dest, uint256 len) internal pure { + // Copy word-length chunks while possible + for (; len > WORD_LENGTH; len -= WORD_LENGTH) { + assembly { + mstore(dest, mload(src)) + } + dest += WORD_LENGTH; + src += WORD_LENGTH; + } + + // Copy remaining bytes + uint256 mask = 256**(WORD_LENGTH - len) - 1; + assembly { + let srcpart := and(mload(src), not(mask)) + let destpart := and(mload(dest), mask) + mstore(dest, or(destpart, srcpart)) + } + } + + /** + * @dev Use assembly to get memory address. + * @param r The in-memory bytes array + * @return The memory address of `r` + */ + function getMemoryAddress(bytes memory r) internal pure returns (uint256) { + uint256 addr; + assembly { + addr := r + } + return addr; + } + + /** + * @dev Implement Math function of ceil + * @param a The denominator + * @param m The numerator + * @return r The result of ceil(a/m) + */ + function ceil(uint256 a, uint256 m) internal pure returns (uint256 r) { + return (a + m - 1) / m; + } + + // Decoders + /** + * This section of code `_decode_(u)int(32|64)`, `_decode_enum` and `_decode_bool` + * is to decode ProtoBuf native integers, + * using the `varint` encoding. + */ + + /** + * @dev Decode integers + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded integer + * @return The length of `bs` used to get decoded + */ + function _decode_uint32(uint256 p, bytes memory bs) + internal + pure + returns (uint32, uint256) + { + (uint256 varint, uint256 sz) = _decode_varint(p, bs); + return (uint32(varint), sz); + } + + /** + * @dev Decode integers + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded integer + * @return The length of `bs` used to get decoded + */ + function _decode_uint64(uint256 p, bytes memory bs) + internal + pure + returns (uint64, uint256) + { + (uint256 varint, uint256 sz) = _decode_varint(p, bs); + return (uint64(varint), sz); + } + + /** + * @dev Decode integers + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded integer + * @return The length of `bs` used to get decoded + */ + function _decode_int32(uint256 p, bytes memory bs) + internal + pure + returns (int32, uint256) + { + (uint256 varint, uint256 sz) = _decode_varint(p, bs); + int32 r; + assembly { + r := varint + } + return (r, sz); + } + + /** + * @dev Decode integers + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded integer + * @return The length of `bs` used to get decoded + */ + function _decode_int64(uint256 p, bytes memory bs) + internal + pure + returns (int64, uint256) + { + (uint256 varint, uint256 sz) = _decode_varint(p, bs); + int64 r; + assembly { + r := varint + } + return (r, sz); + } + + /** + * @dev Decode enum + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded enum's integer + * @return The length of `bs` used to get decoded + */ + function _decode_enum(uint256 p, bytes memory bs) + internal + pure + returns (int64, uint256) + { + return _decode_int64(p, bs); + } + + /** + * @dev Decode enum + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded boolean + * @return The length of `bs` used to get decoded + */ + function _decode_bool(uint256 p, bytes memory bs) + internal + pure + returns (bool, uint256) + { + (uint256 varint, uint256 sz) = _decode_varint(p, bs); + if (varint == 0) { + return (false, sz); + } + return (true, sz); + } + + /** + * This section of code `_decode_sint(32|64)` + * is to decode ProtoBuf native signed integers, + * using the `zig-zag` encoding. + */ + + /** + * @dev Decode signed integers + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded integer + * @return The length of `bs` used to get decoded + */ + function _decode_sint32(uint256 p, bytes memory bs) + internal + pure + returns (int32, uint256) + { + (int256 varint, uint256 sz) = _decode_varints(p, bs); + return (int32(varint), sz); + } + + /** + * @dev Decode signed integers + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded integer + * @return The length of `bs` used to get decoded + */ + function _decode_sint64(uint256 p, bytes memory bs) + internal + pure + returns (int64, uint256) + { + (int256 varint, uint256 sz) = _decode_varints(p, bs); + return (int64(varint), sz); + } + + /** + * @dev Decode string + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded string + * @return The length of `bs` used to get decoded + */ + function _decode_string(uint256 p, bytes memory bs) + internal + pure + returns (string memory, uint256) + { + (bytes memory x, uint256 sz) = _decode_lendelim(p, bs); + return (string(x), sz); + } + + /** + * @dev Decode bytes array + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded bytes array + * @return The length of `bs` used to get decoded + */ + function _decode_bytes(uint256 p, bytes memory bs) + internal + pure + returns (bytes memory, uint256) + { + return _decode_lendelim(p, bs); + } + + /** + * @dev Decode ProtoBuf key + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded field ID + * @return The decoded WireType specified in ProtoBuf + * @return The length of `bs` used to get decoded + */ + function _decode_key(uint256 p, bytes memory bs) + internal + pure + returns (uint256, WireType, uint256) + { + (uint256 x, uint256 n) = _decode_varint(p, bs); + WireType typeId = WireType(x & 7); + uint256 fieldId = x / 8; + return (fieldId, typeId, n); + } + + /** + * @dev Decode ProtoBuf varint + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded unsigned integer + * @return The length of `bs` used to get decoded + */ + function _decode_varint(uint256 p, bytes memory bs) + internal + pure + returns (uint256, uint256) + { + /** + * Read a byte. + * Use the lower 7 bits and shift it to the left, + * until the most significant bit is 0. + * Refer to https://developers.google.com/protocol-buffers/docs/encoding + */ + uint256 x = 0; + uint256 sz = 0; + uint256 length = bs.length + WORD_LENGTH; + assembly { + let b := 0x80 + p := add(bs, p) + for { + + } eq(0x80, and(b, 0x80)) { + + } { + if eq(lt(sub(p, bs), length), 0) { + mstore( + 0, + 0x08c379a000000000000000000000000000000000000000000000000000000000 + ) //error function selector + mstore(4, 32) + mstore(36, 15) + mstore( + 68, + 0x6c656e677468206f766572666c6f770000000000000000000000000000000000 + ) // length overflow in hex + revert(0, 83) + } + let tmp := mload(p) + let pos := 0 + for { + + } and(eq(0x80, and(b, 0x80)), lt(pos, 32)) { + + } { + if eq(lt(sub(p, bs), length), 0) { + mstore( + 0, + 0x08c379a000000000000000000000000000000000000000000000000000000000 + ) //error function selector + mstore(4, 32) + mstore(36, 15) + mstore( + 68, + 0x6c656e677468206f766572666c6f770000000000000000000000000000000000 + ) // length overflow in hex + revert(0, 83) + } + b := byte(pos, tmp) + x := or(x, shl(mul(7, sz), and(0x7f, b))) + sz := add(sz, 1) + pos := add(pos, 1) + p := add(p, 0x01) + } + } + } + return (x, sz); + } + + /** + * @dev Decode ProtoBuf zig-zag encoding + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded signed integer + * @return The length of `bs` used to get decoded + */ + function _decode_varints(uint256 p, bytes memory bs) + internal + pure + returns (int256, uint256) + { + /** + * Refer to https://developers.google.com/protocol-buffers/docs/encoding + */ + (uint256 u, uint256 sz) = _decode_varint(p, bs); + int256 s; + assembly { + s := xor(shr(1, u), add(not(and(u, 1)), 1)) + } + return (s, sz); + } + + /** + * @dev Decode ProtoBuf fixed-length encoding + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded unsigned integer + * @return The length of `bs` used to get decoded + */ + function _decode_uintf(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (uint256, uint256) + { + /** + * Refer to https://developers.google.com/protocol-buffers/docs/encoding + */ + uint256 x = 0; + uint256 length = bs.length + WORD_LENGTH; + assert(p + sz <= length); + assembly { + let i := 0 + p := add(bs, p) + let tmp := mload(p) + for { + + } lt(i, sz) { + + } { + x := or(x, shl(mul(8, i), byte(i, tmp))) + p := add(p, 0x01) + i := add(i, 1) + } + } + return (x, sz); + } + + /** + * `_decode_(s)fixed(32|64)` is the concrete implementation of `_decode_uintf` + */ + function _decode_fixed32(uint256 p, bytes memory bs) + internal + pure + returns (uint32, uint256) + { + (uint256 x, uint256 sz) = _decode_uintf(p, bs, 4); + return (uint32(x), sz); + } + + function _decode_fixed64(uint256 p, bytes memory bs) + internal + pure + returns (uint64, uint256) + { + (uint256 x, uint256 sz) = _decode_uintf(p, bs, 8); + return (uint64(x), sz); + } + + function _decode_sfixed32(uint256 p, bytes memory bs) + internal + pure + returns (int32, uint256) + { + (uint256 x, uint256 sz) = _decode_uintf(p, bs, 4); + int256 r; + assembly { + r := x + } + return (int32(r), sz); + } + + function _decode_sfixed64(uint256 p, bytes memory bs) + internal + pure + returns (int64, uint256) + { + (uint256 x, uint256 sz) = _decode_uintf(p, bs, 8); + int256 r; + assembly { + r := x + } + return (int64(r), sz); + } + + /** + * @dev Decode bytes array + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The decoded bytes array + * @return The length of `bs` used to get decoded + */ + function _decode_lendelim(uint256 p, bytes memory bs) + internal + pure + returns (bytes memory, uint256) + { + /** + * First read the size encoded in `varint`, then use the size to read bytes. + */ + (uint256 len, uint256 sz) = _decode_varint(p, bs); + bytes memory b = new bytes(len); + uint256 length = bs.length + WORD_LENGTH; + assert(p + sz + len <= length); + uint256 sourcePtr; + uint256 destPtr; + assembly { + destPtr := add(b, 32) + sourcePtr := add(add(bs, p), sz) + } + copyBytes(sourcePtr, destPtr, len); + return (b, sz + len); + } + + // Encoders + /** + * @dev Encode ProtoBuf key + * @param x The field ID + * @param wt The WireType specified in ProtoBuf + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The length of encoded bytes + */ + function _encode_key(uint256 x, WireType wt, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint256 i; + assembly { + i := or(mul(x, 8), mod(wt, 8)) + } + return _encode_varint(i, p, bs); + } + + /** + * @dev Encode ProtoBuf varint + * @param x The unsigned integer to be encoded + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The length of encoded bytes + */ + function _encode_varint(uint256 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + /** + * Refer to https://developers.google.com/protocol-buffers/docs/encoding + */ + uint256 sz = 0; + assembly { + let bsptr := add(bs, p) + let byt := and(x, 0x7f) + for { + + } gt(shr(7, x), 0) { + + } { + mstore8(bsptr, or(0x80, byt)) + bsptr := add(bsptr, 1) + sz := add(sz, 1) + x := shr(7, x) + byt := and(x, 0x7f) + } + mstore8(bsptr, byt) + sz := add(sz, 1) + } + return sz; + } + + /** + * @dev Encode ProtoBuf zig-zag encoding + * @param x The signed integer to be encoded + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The length of encoded bytes + */ + function _encode_varints(int256 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + /** + * Refer to https://developers.google.com/protocol-buffers/docs/encoding + */ + uint256 encodedInt = _encode_zigzag(x); + return _encode_varint(encodedInt, p, bs); + } + + /** + * @dev Encode ProtoBuf bytes + * @param xs The bytes array to be encoded + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The length of encoded bytes + */ + function _encode_bytes(bytes memory xs, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint256 xsLength = xs.length; + uint256 sz = _encode_varint(xsLength, p, bs); + uint256 count = 0; + assembly { + let bsptr := add(bs, add(p, sz)) + let xsptr := add(xs, 32) + for { + + } lt(count, xsLength) { + + } { + mstore8(bsptr, byte(0, mload(xsptr))) + bsptr := add(bsptr, 1) + xsptr := add(xsptr, 1) + count := add(count, 1) + } + } + return sz + count; + } + + /** + * @dev Encode ProtoBuf string + * @param xs The string to be encoded + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The length of encoded bytes + */ + function _encode_string(string memory xs, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_bytes(bytes(xs), p, bs); + } + + /** + * `_encode_(u)int(32|64)`, `_encode_enum` and `_encode_bool` + * are concrete implementation of `_encode_varint` + */ + function _encode_uint32(uint32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_varint(x, p, bs); + } + + function _encode_uint64(uint64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_varint(x, p, bs); + } + + function _encode_int32(int32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint64 twosComplement; + assembly { + twosComplement := x + } + return _encode_varint(twosComplement, p, bs); + } + + function _encode_int64(int64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint64 twosComplement; + assembly { + twosComplement := x + } + return _encode_varint(twosComplement, p, bs); + } + + function _encode_enum(int32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_int32(x, p, bs); + } + + function _encode_bool(bool x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + if (x) { + return _encode_varint(1, p, bs); + } else return _encode_varint(0, p, bs); + } + + /** + * `_encode_sint(32|64)`, `_encode_enum` and `_encode_bool` + * are the concrete implementation of `_encode_varints` + */ + function _encode_sint32(int32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_varints(x, p, bs); + } + + function _encode_sint64(int64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_varints(x, p, bs); + } + + /** + * `_encode_(s)fixed(32|64)` is the concrete implementation of `_encode_uintf` + */ + function _encode_fixed32(uint32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_uintf(x, p, bs, 4); + } + + function _encode_fixed64(uint64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_uintf(x, p, bs, 8); + } + + function _encode_sfixed32(int32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint32 twosComplement; + assembly { + twosComplement := x + } + return _encode_uintf(twosComplement, p, bs, 4); + } + + function _encode_sfixed64(int64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint64 twosComplement; + assembly { + twosComplement := x + } + return _encode_uintf(twosComplement, p, bs, 8); + } + + /** + * @dev Encode ProtoBuf fixed-length integer + * @param x The unsigned integer to be encoded + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The length of encoded bytes + */ + function _encode_uintf(uint256 x, uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (uint256) + { + assembly { + let bsptr := add(sz, add(bs, p)) + let count := sz + for { + + } gt(count, 0) { + + } { + bsptr := sub(bsptr, 1) + mstore8(bsptr, byte(sub(32, count), x)) + count := sub(count, 1) + } + } + return sz; + } + + /** + * @dev Encode ProtoBuf zig-zag signed integer + * @param i The unsigned integer to be encoded + * @return The encoded unsigned integer + */ + function _encode_zigzag(int256 i) internal pure returns (uint256) { + if (i >= 0) { + return uint256(i) * 2; + } else return uint256(i * -2) - 1; + } + + // Estimators + /** + * @dev Estimate the length of encoded LengthDelim + * @param i The length of LengthDelim + * @return The estimated encoded length + */ + function _sz_lendelim(uint256 i) internal pure returns (uint256) { + return i + _sz_varint(i); + } + + /** + * @dev Estimate the length of encoded ProtoBuf field ID + * @param i The field ID + * @return The estimated encoded length + */ + function _sz_key(uint256 i) internal pure returns (uint256) { + if (i < 16) { + return 1; + } else if (i < 2048) { + return 2; + } else if (i < 262144) { + return 3; + } else { + revert("not supported"); + } + } + + /** + * @dev Estimate the length of encoded ProtoBuf varint + * @param i The unsigned integer + * @return The estimated encoded length + */ + function _sz_varint(uint256 i) internal pure returns (uint256) { + uint256 count = 1; + assembly { + i := shr(7, i) + for { + + } gt(i, 0) { + + } { + i := shr(7, i) + count := add(count, 1) + } + } + return count; + } + + /** + * `_sz_(u)int(32|64)` and `_sz_enum` are the concrete implementation of `_sz_varint` + */ + function _sz_uint32(uint32 i) internal pure returns (uint256) { + return _sz_varint(i); + } + + function _sz_uint64(uint64 i) internal pure returns (uint256) { + return _sz_varint(i); + } + + function _sz_int32(int32 i) internal pure returns (uint256) { + if (i < 0) { + return 10; + } else return _sz_varint(uint32(i)); + } + + function _sz_int64(int64 i) internal pure returns (uint256) { + if (i < 0) { + return 10; + } else return _sz_varint(uint64(i)); + } + + function _sz_enum(int64 i) internal pure returns (uint256) { + if (i < 0) { + return 10; + } else return _sz_varint(uint64(i)); + } + + /** + * `_sz_sint(32|64)` and `_sz_enum` are the concrete implementation of zig-zag encoding + */ + function _sz_sint32(int32 i) internal pure returns (uint256) { + return _sz_varint(_encode_zigzag(i)); + } + + function _sz_sint64(int64 i) internal pure returns (uint256) { + return _sz_varint(_encode_zigzag(i)); + } + + // Soltype extensions + /** + * @dev Decode Solidity integer and/or fixed-size bytes array, filling from lowest bit. + * @param n The maximum number of bytes to read + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The bytes32 representation + * @return The number of bytes used to decode + */ + function _decode_sol_bytesN_lower(uint8 n, uint256 p, bytes memory bs) + internal + pure + returns (bytes32, uint256) + { + uint256 r; + (uint256 len, uint256 sz) = _decode_varint(p, bs); + if (len + sz > n + 3) { + revert(OVERFLOW_MESSAGE); + } + p += 3; + assert(p < bs.length + WORD_LENGTH); + assembly { + r := mload(add(p, bs)) + } + for (uint256 i = len - 2; i < WORD_LENGTH; i++) { + r /= 256; + } + return (bytes32(r), len + sz); + } + + /** + * @dev Decode Solidity integer and/or fixed-size bytes array, filling from highest bit. + * @param n The maximum number of bytes to read + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The bytes32 representation + * @return The number of bytes used to decode + */ + function _decode_sol_bytesN(uint8 n, uint256 p, bytes memory bs) + internal + pure + returns (bytes32, uint256) + { + (uint256 len, uint256 sz) = _decode_varint(p, bs); + uint256 wordLength = WORD_LENGTH; + uint256 byteSize = BYTE_SIZE; + if (len + sz > n + 3) { + revert(OVERFLOW_MESSAGE); + } + p += 3; + bytes32 acc; + assert(p < bs.length + WORD_LENGTH); + assembly { + acc := mload(add(p, bs)) + let difference := sub(wordLength, sub(len, 2)) + let bits := mul(byteSize, difference) + acc := shl(bits, shr(bits, acc)) + } + return (acc, len + sz); + } + + /* + * `_decode_sol*` are the concrete implementation of decoding Solidity types + */ + function _decode_sol_address(uint256 p, bytes memory bs) + internal + pure + returns (address, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytesN(20, p, bs); + return (address(bytes20(r)), sz); + } + + function _decode_sol_bool(uint256 p, bytes memory bs) + internal + pure + returns (bool, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(1, p, bs); + if (r == 0) { + return (false, sz); + } + return (true, sz); + } + + function _decode_sol_uint(uint256 p, bytes memory bs) + internal + pure + returns (uint256, uint256) + { + return _decode_sol_uint256(p, bs); + } + + function _decode_sol_uintN(uint8 n, uint256 p, bytes memory bs) + internal + pure + returns (uint256, uint256) + { + (bytes32 u, uint256 sz) = _decode_sol_bytesN_lower(n, p, bs); + uint256 r; + assembly { + r := u + } + return (r, sz); + } + + function _decode_sol_uint8(uint256 p, bytes memory bs) + internal + pure + returns (uint8, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(1, p, bs); + return (uint8(r), sz); + } + + function _decode_sol_uint16(uint256 p, bytes memory bs) + internal + pure + returns (uint16, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(2, p, bs); + return (uint16(r), sz); + } + + function _decode_sol_uint24(uint256 p, bytes memory bs) + internal + pure + returns (uint24, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(3, p, bs); + return (uint24(r), sz); + } + + function _decode_sol_uint32(uint256 p, bytes memory bs) + internal + pure + returns (uint32, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(4, p, bs); + return (uint32(r), sz); + } + + function _decode_sol_uint40(uint256 p, bytes memory bs) + internal + pure + returns (uint40, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(5, p, bs); + return (uint40(r), sz); + } + + function _decode_sol_uint48(uint256 p, bytes memory bs) + internal + pure + returns (uint48, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(6, p, bs); + return (uint48(r), sz); + } + + function _decode_sol_uint56(uint256 p, bytes memory bs) + internal + pure + returns (uint56, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(7, p, bs); + return (uint56(r), sz); + } + + function _decode_sol_uint64(uint256 p, bytes memory bs) + internal + pure + returns (uint64, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(8, p, bs); + return (uint64(r), sz); + } + + function _decode_sol_uint72(uint256 p, bytes memory bs) + internal + pure + returns (uint72, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(9, p, bs); + return (uint72(r), sz); + } + + function _decode_sol_uint80(uint256 p, bytes memory bs) + internal + pure + returns (uint80, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(10, p, bs); + return (uint80(r), sz); + } + + function _decode_sol_uint88(uint256 p, bytes memory bs) + internal + pure + returns (uint88, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(11, p, bs); + return (uint88(r), sz); + } + + function _decode_sol_uint96(uint256 p, bytes memory bs) + internal + pure + returns (uint96, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(12, p, bs); + return (uint96(r), sz); + } + + function _decode_sol_uint104(uint256 p, bytes memory bs) + internal + pure + returns (uint104, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(13, p, bs); + return (uint104(r), sz); + } + + function _decode_sol_uint112(uint256 p, bytes memory bs) + internal + pure + returns (uint112, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(14, p, bs); + return (uint112(r), sz); + } + + function _decode_sol_uint120(uint256 p, bytes memory bs) + internal + pure + returns (uint120, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(15, p, bs); + return (uint120(r), sz); + } + + function _decode_sol_uint128(uint256 p, bytes memory bs) + internal + pure + returns (uint128, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(16, p, bs); + return (uint128(r), sz); + } + + function _decode_sol_uint136(uint256 p, bytes memory bs) + internal + pure + returns (uint136, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(17, p, bs); + return (uint136(r), sz); + } + + function _decode_sol_uint144(uint256 p, bytes memory bs) + internal + pure + returns (uint144, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(18, p, bs); + return (uint144(r), sz); + } + + function _decode_sol_uint152(uint256 p, bytes memory bs) + internal + pure + returns (uint152, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(19, p, bs); + return (uint152(r), sz); + } + + function _decode_sol_uint160(uint256 p, bytes memory bs) + internal + pure + returns (uint160, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(20, p, bs); + return (uint160(r), sz); + } + + function _decode_sol_uint168(uint256 p, bytes memory bs) + internal + pure + returns (uint168, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(21, p, bs); + return (uint168(r), sz); + } + + function _decode_sol_uint176(uint256 p, bytes memory bs) + internal + pure + returns (uint176, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(22, p, bs); + return (uint176(r), sz); + } + + function _decode_sol_uint184(uint256 p, bytes memory bs) + internal + pure + returns (uint184, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(23, p, bs); + return (uint184(r), sz); + } + + function _decode_sol_uint192(uint256 p, bytes memory bs) + internal + pure + returns (uint192, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(24, p, bs); + return (uint192(r), sz); + } + + function _decode_sol_uint200(uint256 p, bytes memory bs) + internal + pure + returns (uint200, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(25, p, bs); + return (uint200(r), sz); + } + + function _decode_sol_uint208(uint256 p, bytes memory bs) + internal + pure + returns (uint208, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(26, p, bs); + return (uint208(r), sz); + } + + function _decode_sol_uint216(uint256 p, bytes memory bs) + internal + pure + returns (uint216, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(27, p, bs); + return (uint216(r), sz); + } + + function _decode_sol_uint224(uint256 p, bytes memory bs) + internal + pure + returns (uint224, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(28, p, bs); + return (uint224(r), sz); + } + + function _decode_sol_uint232(uint256 p, bytes memory bs) + internal + pure + returns (uint232, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(29, p, bs); + return (uint232(r), sz); + } + + function _decode_sol_uint240(uint256 p, bytes memory bs) + internal + pure + returns (uint240, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(30, p, bs); + return (uint240(r), sz); + } + + function _decode_sol_uint248(uint256 p, bytes memory bs) + internal + pure + returns (uint248, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(31, p, bs); + return (uint248(r), sz); + } + + function _decode_sol_uint256(uint256 p, bytes memory bs) + internal + pure + returns (uint256, uint256) + { + (uint256 r, uint256 sz) = _decode_sol_uintN(32, p, bs); + return (uint256(r), sz); + } + + function _decode_sol_int(uint256 p, bytes memory bs) + internal + pure + returns (int256, uint256) + { + return _decode_sol_int256(p, bs); + } + + function _decode_sol_intN(uint8 n, uint256 p, bytes memory bs) + internal + pure + returns (int256, uint256) + { + (bytes32 u, uint256 sz) = _decode_sol_bytesN_lower(n, p, bs); + int256 r; + assembly { + r := u + r := signextend(sub(sz, 4), r) + } + return (r, sz); + } + + function _decode_sol_bytes(uint8 n, uint256 p, bytes memory bs) + internal + pure + returns (bytes32, uint256) + { + (bytes32 u, uint256 sz) = _decode_sol_bytesN(n, p, bs); + return (u, sz); + } + + function _decode_sol_int8(uint256 p, bytes memory bs) + internal + pure + returns (int8, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(1, p, bs); + return (int8(r), sz); + } + + function _decode_sol_int16(uint256 p, bytes memory bs) + internal + pure + returns (int16, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(2, p, bs); + return (int16(r), sz); + } + + function _decode_sol_int24(uint256 p, bytes memory bs) + internal + pure + returns (int24, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(3, p, bs); + return (int24(r), sz); + } + + function _decode_sol_int32(uint256 p, bytes memory bs) + internal + pure + returns (int32, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(4, p, bs); + return (int32(r), sz); + } + + function _decode_sol_int40(uint256 p, bytes memory bs) + internal + pure + returns (int40, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(5, p, bs); + return (int40(r), sz); + } + + function _decode_sol_int48(uint256 p, bytes memory bs) + internal + pure + returns (int48, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(6, p, bs); + return (int48(r), sz); + } + + function _decode_sol_int56(uint256 p, bytes memory bs) + internal + pure + returns (int56, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(7, p, bs); + return (int56(r), sz); + } + + function _decode_sol_int64(uint256 p, bytes memory bs) + internal + pure + returns (int64, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(8, p, bs); + return (int64(r), sz); + } + + function _decode_sol_int72(uint256 p, bytes memory bs) + internal + pure + returns (int72, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(9, p, bs); + return (int72(r), sz); + } + + function _decode_sol_int80(uint256 p, bytes memory bs) + internal + pure + returns (int80, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(10, p, bs); + return (int80(r), sz); + } + + function _decode_sol_int88(uint256 p, bytes memory bs) + internal + pure + returns (int88, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(11, p, bs); + return (int88(r), sz); + } + + function _decode_sol_int96(uint256 p, bytes memory bs) + internal + pure + returns (int96, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(12, p, bs); + return (int96(r), sz); + } + + function _decode_sol_int104(uint256 p, bytes memory bs) + internal + pure + returns (int104, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(13, p, bs); + return (int104(r), sz); + } + + function _decode_sol_int112(uint256 p, bytes memory bs) + internal + pure + returns (int112, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(14, p, bs); + return (int112(r), sz); + } + + function _decode_sol_int120(uint256 p, bytes memory bs) + internal + pure + returns (int120, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(15, p, bs); + return (int120(r), sz); + } + + function _decode_sol_int128(uint256 p, bytes memory bs) + internal + pure + returns (int128, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(16, p, bs); + return (int128(r), sz); + } + + function _decode_sol_int136(uint256 p, bytes memory bs) + internal + pure + returns (int136, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(17, p, bs); + return (int136(r), sz); + } + + function _decode_sol_int144(uint256 p, bytes memory bs) + internal + pure + returns (int144, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(18, p, bs); + return (int144(r), sz); + } + + function _decode_sol_int152(uint256 p, bytes memory bs) + internal + pure + returns (int152, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(19, p, bs); + return (int152(r), sz); + } + + function _decode_sol_int160(uint256 p, bytes memory bs) + internal + pure + returns (int160, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(20, p, bs); + return (int160(r), sz); + } + + function _decode_sol_int168(uint256 p, bytes memory bs) + internal + pure + returns (int168, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(21, p, bs); + return (int168(r), sz); + } + + function _decode_sol_int176(uint256 p, bytes memory bs) + internal + pure + returns (int176, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(22, p, bs); + return (int176(r), sz); + } + + function _decode_sol_int184(uint256 p, bytes memory bs) + internal + pure + returns (int184, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(23, p, bs); + return (int184(r), sz); + } + + function _decode_sol_int192(uint256 p, bytes memory bs) + internal + pure + returns (int192, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(24, p, bs); + return (int192(r), sz); + } + + function _decode_sol_int200(uint256 p, bytes memory bs) + internal + pure + returns (int200, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(25, p, bs); + return (int200(r), sz); + } + + function _decode_sol_int208(uint256 p, bytes memory bs) + internal + pure + returns (int208, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(26, p, bs); + return (int208(r), sz); + } + + function _decode_sol_int216(uint256 p, bytes memory bs) + internal + pure + returns (int216, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(27, p, bs); + return (int216(r), sz); + } + + function _decode_sol_int224(uint256 p, bytes memory bs) + internal + pure + returns (int224, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(28, p, bs); + return (int224(r), sz); + } + + function _decode_sol_int232(uint256 p, bytes memory bs) + internal + pure + returns (int232, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(29, p, bs); + return (int232(r), sz); + } + + function _decode_sol_int240(uint256 p, bytes memory bs) + internal + pure + returns (int240, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(30, p, bs); + return (int240(r), sz); + } + + function _decode_sol_int248(uint256 p, bytes memory bs) + internal + pure + returns (int248, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(31, p, bs); + return (int248(r), sz); + } + + function _decode_sol_int256(uint256 p, bytes memory bs) + internal + pure + returns (int256, uint256) + { + (int256 r, uint256 sz) = _decode_sol_intN(32, p, bs); + return (int256(r), sz); + } + + function _decode_sol_bytes1(uint256 p, bytes memory bs) + internal + pure + returns (bytes1, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(1, p, bs); + return (bytes1(r), sz); + } + + function _decode_sol_bytes2(uint256 p, bytes memory bs) + internal + pure + returns (bytes2, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(2, p, bs); + return (bytes2(r), sz); + } + + function _decode_sol_bytes3(uint256 p, bytes memory bs) + internal + pure + returns (bytes3, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(3, p, bs); + return (bytes3(r), sz); + } + + function _decode_sol_bytes4(uint256 p, bytes memory bs) + internal + pure + returns (bytes4, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(4, p, bs); + return (bytes4(r), sz); + } + + function _decode_sol_bytes5(uint256 p, bytes memory bs) + internal + pure + returns (bytes5, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(5, p, bs); + return (bytes5(r), sz); + } + + function _decode_sol_bytes6(uint256 p, bytes memory bs) + internal + pure + returns (bytes6, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(6, p, bs); + return (bytes6(r), sz); + } + + function _decode_sol_bytes7(uint256 p, bytes memory bs) + internal + pure + returns (bytes7, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(7, p, bs); + return (bytes7(r), sz); + } + + function _decode_sol_bytes8(uint256 p, bytes memory bs) + internal + pure + returns (bytes8, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(8, p, bs); + return (bytes8(r), sz); + } + + function _decode_sol_bytes9(uint256 p, bytes memory bs) + internal + pure + returns (bytes9, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(9, p, bs); + return (bytes9(r), sz); + } + + function _decode_sol_bytes10(uint256 p, bytes memory bs) + internal + pure + returns (bytes10, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(10, p, bs); + return (bytes10(r), sz); + } + + function _decode_sol_bytes11(uint256 p, bytes memory bs) + internal + pure + returns (bytes11, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(11, p, bs); + return (bytes11(r), sz); + } + + function _decode_sol_bytes12(uint256 p, bytes memory bs) + internal + pure + returns (bytes12, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(12, p, bs); + return (bytes12(r), sz); + } + + function _decode_sol_bytes13(uint256 p, bytes memory bs) + internal + pure + returns (bytes13, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(13, p, bs); + return (bytes13(r), sz); + } + + function _decode_sol_bytes14(uint256 p, bytes memory bs) + internal + pure + returns (bytes14, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(14, p, bs); + return (bytes14(r), sz); + } + + function _decode_sol_bytes15(uint256 p, bytes memory bs) + internal + pure + returns (bytes15, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(15, p, bs); + return (bytes15(r), sz); + } + + function _decode_sol_bytes16(uint256 p, bytes memory bs) + internal + pure + returns (bytes16, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(16, p, bs); + return (bytes16(r), sz); + } + + function _decode_sol_bytes17(uint256 p, bytes memory bs) + internal + pure + returns (bytes17, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(17, p, bs); + return (bytes17(r), sz); + } + + function _decode_sol_bytes18(uint256 p, bytes memory bs) + internal + pure + returns (bytes18, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(18, p, bs); + return (bytes18(r), sz); + } + + function _decode_sol_bytes19(uint256 p, bytes memory bs) + internal + pure + returns (bytes19, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(19, p, bs); + return (bytes19(r), sz); + } + + function _decode_sol_bytes20(uint256 p, bytes memory bs) + internal + pure + returns (bytes20, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(20, p, bs); + return (bytes20(r), sz); + } + + function _decode_sol_bytes21(uint256 p, bytes memory bs) + internal + pure + returns (bytes21, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(21, p, bs); + return (bytes21(r), sz); + } + + function _decode_sol_bytes22(uint256 p, bytes memory bs) + internal + pure + returns (bytes22, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(22, p, bs); + return (bytes22(r), sz); + } + + function _decode_sol_bytes23(uint256 p, bytes memory bs) + internal + pure + returns (bytes23, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(23, p, bs); + return (bytes23(r), sz); + } + + function _decode_sol_bytes24(uint256 p, bytes memory bs) + internal + pure + returns (bytes24, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(24, p, bs); + return (bytes24(r), sz); + } + + function _decode_sol_bytes25(uint256 p, bytes memory bs) + internal + pure + returns (bytes25, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(25, p, bs); + return (bytes25(r), sz); + } + + function _decode_sol_bytes26(uint256 p, bytes memory bs) + internal + pure + returns (bytes26, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(26, p, bs); + return (bytes26(r), sz); + } + + function _decode_sol_bytes27(uint256 p, bytes memory bs) + internal + pure + returns (bytes27, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(27, p, bs); + return (bytes27(r), sz); + } + + function _decode_sol_bytes28(uint256 p, bytes memory bs) + internal + pure + returns (bytes28, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(28, p, bs); + return (bytes28(r), sz); + } + + function _decode_sol_bytes29(uint256 p, bytes memory bs) + internal + pure + returns (bytes29, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(29, p, bs); + return (bytes29(r), sz); + } + + function _decode_sol_bytes30(uint256 p, bytes memory bs) + internal + pure + returns (bytes30, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(30, p, bs); + return (bytes30(r), sz); + } + + function _decode_sol_bytes31(uint256 p, bytes memory bs) + internal + pure + returns (bytes31, uint256) + { + (bytes32 r, uint256 sz) = _decode_sol_bytes(31, p, bs); + return (bytes31(r), sz); + } + + function _decode_sol_bytes32(uint256 p, bytes memory bs) + internal + pure + returns (bytes32, uint256) + { + return _decode_sol_bytes(32, p, bs); + } + + /* + * `_encode_sol*` are the concrete implementation of encoding Solidity types + */ + function _encode_sol_address(address x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(uint160(x)), 20, p, bs); + } + + function _encode_sol_uint(uint256 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 32, p, bs); + } + + function _encode_sol_uint8(uint8 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 1, p, bs); + } + + function _encode_sol_uint16(uint16 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 2, p, bs); + } + + function _encode_sol_uint24(uint24 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 3, p, bs); + } + + function _encode_sol_uint32(uint32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 4, p, bs); + } + + function _encode_sol_uint40(uint40 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 5, p, bs); + } + + function _encode_sol_uint48(uint48 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 6, p, bs); + } + + function _encode_sol_uint56(uint56 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 7, p, bs); + } + + function _encode_sol_uint64(uint64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 8, p, bs); + } + + function _encode_sol_uint72(uint72 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 9, p, bs); + } + + function _encode_sol_uint80(uint80 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 10, p, bs); + } + + function _encode_sol_uint88(uint88 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 11, p, bs); + } + + function _encode_sol_uint96(uint96 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 12, p, bs); + } + + function _encode_sol_uint104(uint104 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 13, p, bs); + } + + function _encode_sol_uint112(uint112 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 14, p, bs); + } + + function _encode_sol_uint120(uint120 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 15, p, bs); + } + + function _encode_sol_uint128(uint128 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 16, p, bs); + } + + function _encode_sol_uint136(uint136 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 17, p, bs); + } + + function _encode_sol_uint144(uint144 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 18, p, bs); + } + + function _encode_sol_uint152(uint152 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 19, p, bs); + } + + function _encode_sol_uint160(uint160 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 20, p, bs); + } + + function _encode_sol_uint168(uint168 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 21, p, bs); + } + + function _encode_sol_uint176(uint176 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 22, p, bs); + } + + function _encode_sol_uint184(uint184 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 23, p, bs); + } + + function _encode_sol_uint192(uint192 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 24, p, bs); + } + + function _encode_sol_uint200(uint200 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 25, p, bs); + } + + function _encode_sol_uint208(uint208 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 26, p, bs); + } + + function _encode_sol_uint216(uint216 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 27, p, bs); + } + + function _encode_sol_uint224(uint224 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 28, p, bs); + } + + function _encode_sol_uint232(uint232 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 29, p, bs); + } + + function _encode_sol_uint240(uint240 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 30, p, bs); + } + + function _encode_sol_uint248(uint248 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 31, p, bs); + } + + function _encode_sol_uint256(uint256 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(uint256(x), 32, p, bs); + } + + function _encode_sol_int(int256 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(x, 32, p, bs); + } + + function _encode_sol_int8(int8 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 1, p, bs); + } + + function _encode_sol_int16(int16 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 2, p, bs); + } + + function _encode_sol_int24(int24 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 3, p, bs); + } + + function _encode_sol_int32(int32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 4, p, bs); + } + + function _encode_sol_int40(int40 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 5, p, bs); + } + + function _encode_sol_int48(int48 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 6, p, bs); + } + + function _encode_sol_int56(int56 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 7, p, bs); + } + + function _encode_sol_int64(int64 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 8, p, bs); + } + + function _encode_sol_int72(int72 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 9, p, bs); + } + + function _encode_sol_int80(int80 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 10, p, bs); + } + + function _encode_sol_int88(int88 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 11, p, bs); + } + + function _encode_sol_int96(int96 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 12, p, bs); + } + + function _encode_sol_int104(int104 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 13, p, bs); + } + + function _encode_sol_int112(int112 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 14, p, bs); + } + + function _encode_sol_int120(int120 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 15, p, bs); + } + + function _encode_sol_int128(int128 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 16, p, bs); + } + + function _encode_sol_int136(int136 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 17, p, bs); + } + + function _encode_sol_int144(int144 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 18, p, bs); + } + + function _encode_sol_int152(int152 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 19, p, bs); + } + + function _encode_sol_int160(int160 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 20, p, bs); + } + + function _encode_sol_int168(int168 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 21, p, bs); + } + + function _encode_sol_int176(int176 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 22, p, bs); + } + + function _encode_sol_int184(int184 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 23, p, bs); + } + + function _encode_sol_int192(int192 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 24, p, bs); + } + + function _encode_sol_int200(int200 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 25, p, bs); + } + + function _encode_sol_int208(int208 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 26, p, bs); + } + + function _encode_sol_int216(int216 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 27, p, bs); + } + + function _encode_sol_int224(int224 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 28, p, bs); + } + + function _encode_sol_int232(int232 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 29, p, bs); + } + + function _encode_sol_int240(int240 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 30, p, bs); + } + + function _encode_sol_int248(int248 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(int256(x), 31, p, bs); + } + + function _encode_sol_int256(int256 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol(x, 32, p, bs); + } + + function _encode_sol_bytes1(bytes1 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 1, p, bs); + } + + function _encode_sol_bytes2(bytes2 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 2, p, bs); + } + + function _encode_sol_bytes3(bytes3 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 3, p, bs); + } + + function _encode_sol_bytes4(bytes4 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 4, p, bs); + } + + function _encode_sol_bytes5(bytes5 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 5, p, bs); + } + + function _encode_sol_bytes6(bytes6 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 6, p, bs); + } + + function _encode_sol_bytes7(bytes7 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 7, p, bs); + } + + function _encode_sol_bytes8(bytes8 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 8, p, bs); + } + + function _encode_sol_bytes9(bytes9 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 9, p, bs); + } + + function _encode_sol_bytes10(bytes10 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 10, p, bs); + } + + function _encode_sol_bytes11(bytes11 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 11, p, bs); + } + + function _encode_sol_bytes12(bytes12 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 12, p, bs); + } + + function _encode_sol_bytes13(bytes13 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 13, p, bs); + } + + function _encode_sol_bytes14(bytes14 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 14, p, bs); + } + + function _encode_sol_bytes15(bytes15 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 15, p, bs); + } + + function _encode_sol_bytes16(bytes16 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 16, p, bs); + } + + function _encode_sol_bytes17(bytes17 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 17, p, bs); + } + + function _encode_sol_bytes18(bytes18 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 18, p, bs); + } + + function _encode_sol_bytes19(bytes19 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 19, p, bs); + } + + function _encode_sol_bytes20(bytes20 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 20, p, bs); + } + + function _encode_sol_bytes21(bytes21 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 21, p, bs); + } + + function _encode_sol_bytes22(bytes22 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 22, p, bs); + } + + function _encode_sol_bytes23(bytes23 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 23, p, bs); + } + + function _encode_sol_bytes24(bytes24 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 24, p, bs); + } + + function _encode_sol_bytes25(bytes25 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 25, p, bs); + } + + function _encode_sol_bytes26(bytes26 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 26, p, bs); + } + + function _encode_sol_bytes27(bytes27 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 27, p, bs); + } + + function _encode_sol_bytes28(bytes28 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 28, p, bs); + } + + function _encode_sol_bytes29(bytes29 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 29, p, bs); + } + + function _encode_sol_bytes30(bytes30 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 30, p, bs); + } + + function _encode_sol_bytes31(bytes31 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(bytes32(x), 31, p, bs); + } + + function _encode_sol_bytes32(bytes32 x, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + return _encode_sol_bytes(x, 32, p, bs); + } + + /** + * @dev Encode the key of Solidity integer and/or fixed-size bytes array. + * @param sz The number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes used to encode + */ + function _encode_sol_header(uint256 sz, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint256 offset = p; + p += _encode_varint(sz + 2, p, bs); + p += _encode_key(1, WireType.LengthDelim, p, bs); + p += _encode_varint(sz, p, bs); + return p - offset; + } + + /** + * @dev Encode Solidity type + * @param x The unsinged integer to be encoded + * @param sz The number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes used to encode + */ + function _encode_sol(uint256 x, uint256 sz, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint256 offset = p; + uint256 size; + p += 3; + size = _encode_sol_raw_other(x, p, bs, sz); + p += size; + _encode_sol_header(size, offset, bs); + return p - offset; + } + + /** + * @dev Encode Solidity type + * @param x The signed integer to be encoded + * @param sz The number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes used to encode + */ + function _encode_sol(int256 x, uint256 sz, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint256 offset = p; + uint256 size; + p += 3; + size = _encode_sol_raw_other(x, p, bs, sz); + p += size; + _encode_sol_header(size, offset, bs); + return p - offset; + } + + /** + * @dev Encode Solidity type + * @param x The fixed-size byte array to be encoded + * @param sz The number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes used to encode + */ + function _encode_sol_bytes(bytes32 x, uint256 sz, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + uint256 offset = p; + uint256 size; + p += 3; + size = _encode_sol_raw_bytes_array(x, p, bs, sz); + p += size; + _encode_sol_header(size, offset, bs); + return p - offset; + } + + /** + * @dev Get the actual size needed to encoding an unsigned integer + * @param x The unsigned integer to be encoded + * @param sz The maximum number of bytes used to encode Solidity types + * @return The number of bytes needed for encoding `x` + */ + function _get_real_size(uint256 x, uint256 sz) + internal + pure + returns (uint256) + { + uint256 base = 0xff; + uint256 realSize = sz; + while ( + x & (base << (realSize * BYTE_SIZE - BYTE_SIZE)) == 0 && realSize > 0 + ) { + realSize -= 1; + } + if (realSize == 0) { + realSize = 1; + } + return realSize; + } + + /** + * @dev Get the actual size needed to encoding an signed integer + * @param x The signed integer to be encoded + * @param sz The maximum number of bytes used to encode Solidity types + * @return The number of bytes needed for encoding `x` + */ + function _get_real_size(int256 x, uint256 sz) + internal + pure + returns (uint256) + { + int256 base = 0xff; + if (x >= 0) { + uint256 tmp = _get_real_size(uint256(x), sz); + int256 remainder = (x & (base << (tmp * BYTE_SIZE - BYTE_SIZE))) >> + (tmp * BYTE_SIZE - BYTE_SIZE); + if (remainder >= 128) { + tmp += 1; + } + return tmp; + } + + uint256 realSize = sz; + while ( + x & (base << (realSize * BYTE_SIZE - BYTE_SIZE)) == + (base << (realSize * BYTE_SIZE - BYTE_SIZE)) && + realSize > 0 + ) { + realSize -= 1; + } + { + int256 remainder = (x & (base << (realSize * BYTE_SIZE - BYTE_SIZE))) >> + (realSize * BYTE_SIZE - BYTE_SIZE); + if (remainder < 128) { + realSize += 1; + } + } + return realSize; + } + + /** + * @dev Encode the fixed-bytes array + * @param x The fixed-size byte array to be encoded + * @param sz The maximum number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes needed for encoding `x` + */ + function _encode_sol_raw_bytes_array( + bytes32 x, + uint256 p, + bytes memory bs, + uint256 sz + ) internal pure returns (uint256) { + /** + * The idea is to not encode the leading bytes of zero. + */ + uint256 actualSize = sz; + for (uint256 i = 0; i < sz; i++) { + uint8 current = uint8(x[sz - 1 - i]); + if (current == 0 && actualSize > 1) { + actualSize--; + } else { + break; + } + } + assembly { + let bsptr := add(bs, p) + let count := actualSize + for { + + } gt(count, 0) { + + } { + mstore8(bsptr, byte(sub(actualSize, count), x)) + bsptr := add(bsptr, 1) + count := sub(count, 1) + } + } + return actualSize; + } + + /** + * @dev Encode the signed integer + * @param x The signed integer to be encoded + * @param sz The maximum number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes needed for encoding `x` + */ + function _encode_sol_raw_other( + int256 x, + uint256 p, + bytes memory bs, + uint256 sz + ) internal pure returns (uint256) { + /** + * The idea is to not encode the leading bytes of zero.or one, + * depending on whether it is positive. + */ + uint256 realSize = _get_real_size(x, sz); + assembly { + let bsptr := add(bs, p) + let count := realSize + for { + + } gt(count, 0) { + + } { + mstore8(bsptr, byte(sub(32, count), x)) + bsptr := add(bsptr, 1) + count := sub(count, 1) + } + } + return realSize; + } + + /** + * @dev Encode the unsigned integer + * @param x The unsigned integer to be encoded + * @param sz The maximum number of bytes used to encode Solidity types + * @param p The offset of bytes array `bs` + * @param bs The bytes array to encode + * @return The number of bytes needed for encoding `x` + */ + function _encode_sol_raw_other( + uint256 x, + uint256 p, + bytes memory bs, + uint256 sz + ) internal pure returns (uint256) { + uint256 realSize = _get_real_size(x, sz); + assembly { + let bsptr := add(bs, p) + let count := realSize + for { + + } gt(count, 0) { + + } { + mstore8(bsptr, byte(sub(32, count), x)) + bsptr := add(bsptr, 1) + count := sub(count, 1) + } + } + return realSize; + } +} diff --git a/sol/contracts/ics23.sol b/sol/contracts/ics23.sol new file mode 100644 index 00000000..6a670c49 --- /dev/null +++ b/sol/contracts/ics23.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; +import {BatchProof, CompressedBatchProof, CommitmentProof, ProofSpec, ExistenceProof, NonExistenceProof} from "./proofs.sol"; +import {Compress} from "./ics23Compress.sol"; +import {Proof} from "./ics23Proof.sol"; +import {Ops} from "./ics23Ops.sol"; +import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol"; + +library Ics23 { + + // verifyMembership, throws an exception in case anything goes wrong + function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) internal pure { + CommitmentProof.Data memory decoProof = Compress.decompress(proof); + ExistenceProof.Data memory exiProof = getExistProofForKey(decoProof, key); + require(ExistenceProof.isNil(exiProof) == false); // dev: getExistProofForKey not available + Proof.verify(exiProof, spec, commitmentRoot, key, value); + } + + function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) internal pure { + CommitmentProof.Data memory decoProof = Compress.decompress(proof); + NonExistenceProof.Data memory nonProof = getNonExistProofForKey(decoProof, key); + require(NonExistenceProof.isNil(nonProof) == false); // dev: getNonExistProofForKey not available + Proof.verify(nonProof, spec, commitmentRoot, key); + } +/* -- temporarily disabled as they are not covered by unit tests + struct BatchItem { + bytes key; + bytes value; + } + function batchVerifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, BatchItem[] memory items ) internal pure { + CommitmentProof.Data memory decoProof = Compress.decompress(proof); + for (uint i = 0; i < items.length; i++) { + verifyMembership(spec, commitmentRoot, decoProof, items[i].key, items[i].value); + } + } + + function batchVerifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes[] memory keys ) internal pure { + CommitmentProof.Data memory decoProof = Compress.decompress(proof); + for (uint i = 0; i < keys.length; i++) { + verifyNonMembership(spec, commitmentRoot, decoProof, keys[i]); + } + } +*/ + + // private + function getExistProofForKey(CommitmentProof.Data memory proof, bytes memory key) private pure returns(ExistenceProof.Data memory) { + if (ExistenceProof.isNil(proof.exist) == false){ + if (BytesLib.equal(proof.exist.key, key) == true) { + return proof.exist; + } + } else if(BatchProof.isNil(proof.batch) == false) { + for (uint i = 0; i < proof.batch.entries.length; i++) { + if (ExistenceProof.isNil(proof.batch.entries[i].exist) == false && + BytesLib.equal(proof.batch.entries[i].exist.key, key)) { + return proof.batch.entries[i].exist; + } + } + } + return ExistenceProof.nil(); + } + + function getNonExistProofForKey(CommitmentProof.Data memory proof, bytes memory key) private pure returns(NonExistenceProof.Data memory) { + if (NonExistenceProof.isNil(proof.nonexist) == false) { + if (isLeft(proof.nonexist.left, key) && isRight(proof.nonexist.right, key)) { + return proof.nonexist; + } + } else if (BatchProof.isNil(proof.batch) == false) { + for (uint i = 0; i < proof.batch.entries.length; i++) { + if (NonExistenceProof.isNil(proof.batch.entries[i].nonexist) == false && + isLeft(proof.batch.entries[i].nonexist.left, key) && + isRight(proof.batch.entries[i].nonexist.right, key)) { + return proof.batch.entries[i].nonexist; + } + } + } + return NonExistenceProof.nil(); + } + + function isLeft(ExistenceProof.Data memory left, bytes memory key) private pure returns(bool) { + // ExistenceProof.isNil does not work + return ExistenceProof._empty(left) || Ops.compare(left.key, key) < 0; + } + + function isRight(ExistenceProof.Data memory right, bytes memory key) private pure returns(bool) { + // ExistenceProof.isNil does not work + return ExistenceProof._empty(right) || Ops.compare(right.key, key) > 0; + } +} + + +contract ICS23_UnitTest { + function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) public pure { + Ics23.verifyMembership(spec, commitmentRoot, proof, key, value); + } + function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) public pure { + Ics23.verifyNonMembership(spec, commitmentRoot, proof, key); + } +/* -- temporarily disabled as they are not covered by unit tests + function batchVerifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, Ics23.BatchItem[] memory items ) public pure { + Ics23.batchVerifyMembership(spec, commitmentRoot, proof, items); + } + function batchVerifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes[] memory keys ) public pure { + Ics23.batchVerifyNonMembership(spec, commitmentRoot, proof, keys); + } +*/ +} + diff --git a/sol/contracts/ics23Compress.sol b/sol/contracts/ics23Compress.sol new file mode 100644 index 00000000..66d04f37 --- /dev/null +++ b/sol/contracts/ics23Compress.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; +import {InnerOp, ExistenceProof, NonExistenceProof, CommitmentProof, CompressedBatchEntry, CompressedBatchProof, CompressedExistenceProof, BatchEntry, BatchProof} from "./proofs.sol"; +import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; + +library Compress { + function decompress(CommitmentProof.Data memory proof) internal pure returns(CommitmentProof.Data memory) { + //CompressedBatchProof.isNil() does not work + if (CompressedBatchProof._empty(proof.compressed) == true){ + return proof; + } + return CommitmentProof.Data({ + exist: ExistenceProof.nil(), + nonexist: NonExistenceProof.nil(), + batch: BatchProof.Data({ + entries: decompress(proof.compressed) + }), + compressed: CompressedBatchProof.nil() + }); + } + + // private + function decompress(CompressedBatchProof.Data memory proof) private pure returns(BatchEntry.Data[] memory) { + BatchEntry.Data[] memory entries = new BatchEntry.Data[](proof.entries.length); + for(uint i = 0; i < proof.entries.length; i++) { + entries[i] = decompressEntry(proof.entries[i], proof.lookup_inners); + } + return entries; + } + + function decompressEntry(CompressedBatchEntry.Data memory entry, InnerOp.Data[] memory lookup) private pure returns(BatchEntry.Data memory) { + //CompressedExistenceProof.isNil does not work + if (CompressedExistenceProof._empty(entry.exist) == false) { + return BatchEntry.Data({ + exist: decompressExist(entry.exist, lookup), + nonexist: NonExistenceProof.nil() + }); + } + return BatchEntry.Data({ + exist: ExistenceProof.nil(), + nonexist: NonExistenceProof.Data({ + key: entry.nonexist.key, + left: decompressExist(entry.nonexist.left, lookup), + right: decompressExist(entry.nonexist.right, lookup) + }) + }); + } + + function decompressExist(CompressedExistenceProof.Data memory proof, InnerOp.Data[] memory lookup) private pure returns(ExistenceProof.Data memory) { + if (CompressedExistenceProof._empty(proof)) { + return ExistenceProof.nil(); + } + ExistenceProof.Data memory decoProof = ExistenceProof.Data({ + key: proof.key, + value: proof.value, + leaf: proof.leaf, + path : new InnerOp.Data[](proof.path.length) + }); + for (uint i = 0; i < proof.path.length; i++) { + require(proof.path[i] >= 0); // dev: proof.path < 0 + uint step = SafeCast.toUint256(proof.path[i]); + require(step < lookup.length); // dev: step >= lookup.length + decoProof.path[i] = lookup[step]; + } + return decoProof; + } +} diff --git a/sol/contracts/ics23Ops.sol b/sol/contracts/ics23Ops.sol new file mode 100644 index 00000000..c09c597d --- /dev/null +++ b/sol/contracts/ics23Ops.sol @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +import {LeafOp, InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, ProofSpec} from "./proofs.sol"; +import {ProtoBufRuntime} from "./ProtoBufRuntime.sol"; +import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; +import {Math} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/Math.sol"; +import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol"; + +library Ops { + + // LeafOp operations + function applyOp(LeafOp.Data memory leafOp, bytes memory key, bytes memory value) internal pure returns(bytes memory) { + require(key.length > 0); // dev: Leaf op needs key + require(value.length > 0); // dev: Leaf op needs value + bytes memory pKey = prepareLeafData(leafOp.prehash_key, leafOp.length, key); + bytes memory pValue = prepareLeafData(leafOp.prehash_value, leafOp.length, value); + bytes memory data = bytes.concat(leafOp.prefix, pKey, pValue); + return doHash(leafOp.hash, data); + } + function prepareLeafData(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) internal pure returns(bytes memory) { + bytes memory hdata = doHashOrNoop(hashOp, data); + return doLengthOp(lenOp, hdata); + } + function checkAgainstSpec(LeafOp.Data memory leafOp, ProofSpec.Data memory spec) internal pure { + require (leafOp.hash == spec.leaf_spec.hash); // dev: checkAgainstSpec for LeafOp - Unexpected HashOp + require(leafOp.prehash_key == spec.leaf_spec.prehash_key); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashKey + require(leafOp.prehash_value == spec.leaf_spec.prehash_value); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashValue"); + require(leafOp.length == spec.leaf_spec.length); // dev: checkAgainstSpec for LeafOp - Unexpected lengthOp + bool hasprefix = hasPrefix(leafOp.prefix, spec.leaf_spec.prefix); + require(hasprefix); // dev: checkAgainstSpec for LeafOp - Leaf Prefix doesn't start with + } + + // InnerOp operations + function applyOp(InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory) { + require(child.length > 0); // dev: Inner op needs child value + bytes memory preImage = bytes.concat(innerOp.prefix, child, innerOp.suffix); + return doHash(innerOp.hash, preImage); + } + function checkAgainstSpec(InnerOp.Data memory innerOp, ProofSpec.Data memory spec) internal pure { + require(innerOp.hash == spec.inner_spec.hash); // dev: checkAgainstSpec for InnerOp - Unexpected HashOp + uint256 minPrefixLength = SafeCast.toUint256(spec.inner_spec.min_prefix_length); + require(innerOp.prefix.length >= minPrefixLength); // dev: InnerOp prefix too short; + bytes memory leafPrefix = spec.leaf_spec.prefix; + bool hasprefix = hasPrefix(innerOp.prefix, leafPrefix); + require(hasprefix == false); // dev: Inner Prefix starts with wrong value + uint256 childSize = SafeCast.toUint256(spec.inner_spec.child_size); + uint256 maxLeftChildBytes = (spec.inner_spec.child_order.length - 1) * childSize; + uint256 maxPrefixLength = SafeCast.toUint256(spec.inner_spec.max_prefix_length); + require(innerOp.prefix.length <= maxPrefixLength + maxLeftChildBytes); // dev: InnerOp prefix too long + } + + function doHashOrNoop(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory) { + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.NO_HASH) { + return preImage; + } + return doHash(hashOp, preImage); + } + + function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory) { + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA256) { + return abi.encodePacked(sha256(preImage)); + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.KECCAK) { + return abi.encodePacked(keccak256(preImage)); + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.RIPEMD160) { + return abi.encodePacked(ripemd160(preImage)); + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.BITCOIN) { + bytes memory tmp = abi.encodePacked(sha256(preImage)); + return abi.encodePacked(ripemd160(tmp)); + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA512) { + revert(); // dev: SHA512 not supported + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA512_256) { + revert(); // dev: SHA512_256 not supported + } + revert(); // dev: Unsupported hashOp + } + + function compare(bytes memory a, bytes memory b) internal pure returns(int) { + uint256 minLen = Math.min(a.length, b.length); + for (uint i = 0; i < minLen; i++) { + if (uint8(a[i]) < uint8(b[i])) { + return -1; + } else if (uint8(a[i]) > uint8(b[i])) { + return 1; + } + } + if (a.length > minLen) { + return 1; + } + if (b.length > minLen) { + return -1; + } + return 0; + } + + // private + function doLengthOp(PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) private pure returns(bytes memory) { + if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.NO_PREFIX) { + return data; + } + if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.VAR_PROTO) { + uint256 sz = ProtoBufRuntime._sz_varint(data.length); + bytes memory encoded = new bytes(sz); + ProtoBufRuntime._encode_varint(data.length, 32, encoded); + return bytes.concat(encoded, data); + } + if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.REQUIRE_32_BYTES) { + require(data.length == 32); // dev: data.length != 32 + return data; + } + if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.REQUIRE_64_BYTES) { + require(data.length == 64); // dev: data.length != 64" + return data; + } + if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.FIXED32_LITTLE) { + uint32 size = SafeCast.toUint32(data.length); + // maybe some assembly here to make it faster + bytes4 sizeB = bytes4(size); + bytes memory littleE = new bytes(4); + //unfolding for loop is cheaper + littleE[0] = sizeB[3]; + littleE[1] = sizeB[2]; + littleE[2] = sizeB[1]; + littleE[3] = sizeB[0]; + return bytes.concat(littleE, data); + } + revert(); // dev: Unsupported lenOp + } + + function hasPrefix(bytes memory element, bytes memory prefix) private pure returns (bool) { + if (prefix.length == 0) { + return true; + } + if (prefix.length > element.length) { + return false; + } + bytes memory slice = BytesLib.slice(element, 0, prefix.length); + return BytesLib.equal(prefix, slice); + } +} + + + + +contract Ops_UnitTest { + function applyLeafOp(LeafOp.Data memory leaf, bytes memory key, bytes memory value) public pure returns(bytes memory) { + return Ops.applyOp(leaf, key, value); + } + function checkAgainstLeafOpSpec(LeafOp.Data memory op, ProofSpec.Data memory spec) public pure { + return Ops.checkAgainstSpec(op, spec); + } + function applyInnerOp(InnerOp.Data memory inner,bytes memory child) public pure returns(bytes memory) { + return Ops.applyOp(inner, child); + } + function checkAgainstInnerOpSpec(InnerOp.Data memory op, ProofSpec.Data memory spec) public pure { + return Ops.checkAgainstSpec(op, spec); + } + function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) public pure returns(bytes memory) { + return Ops.doHash(hashOp, preImage); + } +} diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol new file mode 100644 index 00000000..6a4f41b8 --- /dev/null +++ b/sol/contracts/ics23Proof.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; +pragma experimental ABIEncoderV2; + +import {LeafOp, CompressedBatchProof, ExistenceProof, NonExistenceProof, BatchEntry, BatchProof, ProofSpec, InnerOp, InnerSpec, CommitmentProof} from "./proofs.sol"; +import {Ops} from "./ics23Ops.sol"; +import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; +import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol"; +import {Compress} from "./ics23Compress.sol"; +import {Ops} from "./ics23Ops.sol"; + +library Proof{ + // ExistenceProof + function verify(ExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key, bytes memory value) internal pure { + require(BytesLib.equal(proof.key, key)); // dev: Provided key doesn't match proof + require(BytesLib.equal(proof.value, value)); // dev: Provided value doesn't match proof + checkAgainstSpec(proof, spec); + bytes memory root = calculateRoot(proof); + require(BytesLib.equal(root, commitmentRoot)); // dev: Calculcated root doesn't match provided root + } + + function calculateRoot(ExistenceProof.Data memory proof) internal pure returns(bytes memory) { + require(LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp + bytes memory root = Ops.applyOp(proof.leaf, proof.key, proof.value); + for (uint i = 0; i < proof.path.length; i++) { + root = Ops.applyOp(proof.path[i], root); + } + return root; + } + + function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) internal pure { + // LeafOp.isNil does not work + require(LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp + Ops.checkAgainstSpec(proof.leaf, spec); + if (spec.min_depth > 0) { + bool innerOpsDepthTooShort = proof.path.length >= SafeCast.toUint256(int256(spec.min_depth)); + require(innerOpsDepthTooShort); // dev: InnerOps depth too short + } + if (spec.max_depth > 0) { + bool innerOpsDepthTooLong = proof.path.length <= SafeCast.toUint256(int256(spec.max_depth)); + require(innerOpsDepthTooLong); // dev: InnerOps depth too long + } + for(uint i = 0; i < proof.path.length; i++) { + Ops.checkAgainstSpec(proof.path[i], spec); + } + } + + // NonExistenceProof + function verify(NonExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key) internal pure { + bytes memory leftKey; + bytes memory rightKey; + // ExistenceProof.isNil does not work + if (ExistenceProof._empty(proof.left) == false) { + verify(proof.left, spec, commitmentRoot, proof.left.key, proof.left.value); + leftKey = proof.left.key; + } + if (ExistenceProof._empty(proof.right) == false) { + verify(proof.right, spec, commitmentRoot, proof.right.key, proof.right.value); + rightKey = proof.right.key; + } + // If both proofs are missing, this is not a valid proof + require(leftKey.length > 0 || rightKey.length > 0); // dev: both left and right proofs missing + // Ensure in valid range + if (rightKey.length > 0) { + require(Ops.compare(key, rightKey) < 0); // dev: key is not left of right proof + } + if (leftKey.length > 0) { + require(Ops.compare(key, leftKey) > 0); // dev: key is not right of left proof + } + if (leftKey.length == 0) { + require(isLeftMost(spec.inner_spec, proof.right.path)); // dev: left proof missing, right proof must be left-most + } else if (rightKey.length == 0) { + require(isRightMost(spec.inner_spec, proof.left.path)); // dev: isRightMost: right proof missing, left proof must be right-most + } else { + require(isLeftNeighbor(spec.inner_spec, proof.left.path, proof.right.path)); // dev: isLeftNeighbor: right proof missing, left proof must be right-most + } + } + + function calculateRoot(NonExistenceProof.Data memory proof) internal pure returns(bytes memory ) { + if (ExistenceProof._empty(proof.left) == false) { + return calculateRoot(proof.left); + } + if (ExistenceProof._empty(proof.right) == false) { + return calculateRoot(proof.right); + } + revert(); // dev: Nonexistence proof has empty Left and Right proof + } + + // commitment proof + function calculateRoot(CommitmentProof.Data memory proof) internal pure returns(bytes memory) { + if (ExistenceProof._empty(proof.exist) == false) { + return calculateRoot(proof.exist); + } + if (NonExistenceProof._empty(proof.nonexist) == false) { + return calculateRoot(proof.nonexist); + } + if (BatchProof._empty(proof.batch) == false) { + require(proof.batch.entries.length > 0); // dev: batch proof has no entry + require(BatchEntry._empty(proof.batch.entries[0]) == false); // dev: batch proof has empty entry + if (ExistenceProof._empty(proof.batch.entries[0].exist) == false) { + return calculateRoot(proof.batch.entries[0].exist); + } + if (NonExistenceProof._empty(proof.batch.entries[0].nonexist) == false) { + return calculateRoot(proof.batch.entries[0].nonexist); + } + } + if (CompressedBatchProof._empty(proof.compressed) == false) { + return calculateRoot(Compress.decompress(proof)); + } + revert(); // dev: calculateRoot(CommitmentProof) empty proof + } + + + // private + function isLeftMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool) { + (uint minPrefix, uint maxPrefix, uint suffix) = getPadding(spec, 0); + for (uint i = 0; i < path.length; i++) { + if (hasPadding(path[i], minPrefix, maxPrefix, suffix) == false){ + return false; + } + } + return true; + } + + function isRightMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool){ + uint last = spec.child_order.length - 1; + (uint minPrefix, uint maxPrefix, uint suffix) = getPadding(spec, last); + for (uint i = 0; i < path.length; i++) { + if (hasPadding(path[i], minPrefix, maxPrefix, suffix) == false){ + return false; + } + } + return true; + } + + function isLeftNeighbor(InnerSpec.Data memory spec, InnerOp.Data[] memory left, InnerOp.Data[] memory right) private pure returns(bool) { + uint leftIdx = left.length - 1; + uint rightIdx = right.length - 1; + while (leftIdx >= 0 && rightIdx >= 0) { + if (BytesLib.equal(left[leftIdx].prefix, right[rightIdx].prefix) && + BytesLib.equal(left[leftIdx].suffix, right[rightIdx].suffix)) { + leftIdx -= 1; + rightIdx -= 1; + continue; + } + break; + } + if (isLeftStep(spec, left[leftIdx], right[rightIdx]) == false) { + return false; + } + // slicing does not work for ``memory`` types + if (isRightMost(spec, sliceInnerOps(left, 0, leftIdx)) == false){ + return false; + } + if (isLeftMost(spec, sliceInnerOps(right, 0, rightIdx)) == false) { + return false; + } + return true; + } + + function isLeftStep(InnerSpec.Data memory spec, InnerOp.Data memory left, InnerOp.Data memory right) private pure returns(bool){ + uint leftIdx = orderFromPadding(spec, left); + uint rightIdx = orderFromPadding(spec, right); + return rightIdx == leftIdx + 1; + } + + function orderFromPadding(InnerSpec.Data memory spec, InnerOp.Data memory op) private pure returns(uint) { + uint256 maxBranch = spec.child_order.length; + for(uint branch = 0; branch < maxBranch; branch++) { + (uint minp, uint maxp, uint suffix) = getPadding(spec, branch); + if (hasPadding(op, minp, maxp, suffix) == true) { + return branch; + } + } + revert(); // dev: Cannot find any valid spacing for this node + } + + function getPadding(InnerSpec.Data memory spec, uint branch) private pure returns(uint minPrefix, uint maxPrefix, uint suffix) { + uint uChildSize = SafeCast.toUint256(spec.child_size); + uint idx = getPosition(spec.child_order, branch); + uint prefix = idx * uChildSize; + minPrefix = prefix + SafeCast.toUint256(spec.min_prefix_length); + maxPrefix = prefix + SafeCast.toUint256(spec.max_prefix_length); + suffix = (spec.child_order.length - 1 - idx) * uChildSize; + } + + function getPosition(int32[] memory order, uint branch) private pure returns(uint) { + require(branch < order.length); // dev: invalid branch + for (uint i = 0; i < order.length; i++) { + if (SafeCast.toUint256(order[i]) == branch) { + return i; + } + } + revert(); // dev: branch not found in order + } + + function hasPadding(InnerOp.Data memory op, uint minPrefix, uint maxPrefix, uint suffix) private pure returns(bool) { + if (op.prefix.length < minPrefix) return false; + if (op.prefix.length > maxPrefix) return false; + return op.suffix.length == suffix; + } + + function sliceInnerOps(InnerOp.Data[] memory array, uint start, uint end) private pure returns(InnerOp.Data[] memory) { + InnerOp.Data[] memory slice = new InnerOp.Data[](end-start); + for (uint i = start; i < end; i++) { + slice[i] = array[i]; + } + return slice; + } +} + + + + +contract Proof_UnitTest { + function calculateExistenceProofRoot(ExistenceProof.Data memory proof) public pure returns(bytes memory) { + return Proof.calculateRoot(proof); + } + function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) public pure { + return Proof.checkAgainstSpec(proof, spec); + } + function calculateCommitmentProofRoot(CommitmentProof.Data memory proof) public pure returns(bytes memory) { + return Proof.calculateRoot(proof); + } + function protobufDecodeCommitmentProof(bytes memory msg) public pure returns(CommitmentProof.Data memory) { + CommitmentProof.Data memory res = CommitmentProof.decode(msg); + return res; + } +} diff --git a/sol/contracts/proofs.sol b/sol/contracts/proofs.sol new file mode 100644 index 00000000..780024f7 --- /dev/null +++ b/sol/contracts/proofs.sol @@ -0,0 +1,5501 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; +import "./ProtoBufRuntime.sol"; +import "./GoogleProtobufAny.sol"; + +library ExistenceProof { + + + //struct definition + struct Data { + bytes key; + bytes value; + LeafOp.Data leaf; + InnerOp.Data[] path; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.path = new InnerOp.Data[](counters[4]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, nil(), counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, nil(), counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.value = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_leaf( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.leaf = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_path( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.path[r.path.length - counters[4]] = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_LeafOp(uint256 p, bytes memory bs) + internal + pure + returns (LeafOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_InnerOp(uint256 p, bytes memory bs) + internal + pure + returns (InnerOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + if (r.value.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += LeafOp._encode_nested(r.leaf, pointer, bs); + + if (r.path.length != 0) { + for(i = 0; i < r.path.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += InnerOp._encode_nested(r.path[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); + for(i = 0; i < r.path.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.path[i])); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + if (r.value.length != 0) { + return false; + } + + if (r.path.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + output.value = input.value; + LeafOp.store(input.leaf, output.leaf); + + for(uint256 i4 = 0; i4 < input.path.length; i4++) { + output.path.push(input.path[i4]); + } + + + } + + + //array helpers for Path + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addPath(Data memory self, InnerOp.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + InnerOp.Data[] memory tmp = new InnerOp.Data[](self.path.length + 1); + for (uint256 i = 0; i < self.path.length; i++) { + tmp[i] = self.path[i]; + } + tmp[self.path.length] = value; + self.path = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ExistenceProof + +library NonExistenceProof { + + + //struct definition + struct Data { + bytes key; + ExistenceProof.Data left; + ExistenceProof.Data right; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[4] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_left(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_right(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_left( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.left = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_right( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.right = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (ExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.left, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.right, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.right)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + ExistenceProof.store(input.left, output.left); + ExistenceProof.store(input.right, output.right); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library NonExistenceProof + +library CommitmentProof { + + + //struct definition + struct Data { + ExistenceProof.Data exist; + NonExistenceProof.Data nonexist; + BatchProof.Data batch; + CompressedBatchProof.Data compressed; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_exist(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_batch(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_compressed(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.exist = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_nonexist( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.nonexist = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_batch( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (BatchProof.Data memory x, uint256 sz) = _decode_BatchProof(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.batch = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_compressed( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedBatchProof.Data memory x, uint256 sz) = _decode_CompressedBatchProof(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.compressed = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (ExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_NonExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (NonExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_BatchProof(uint256 p, bytes memory bs) + internal + pure + returns (BatchProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (BatchProof.Data memory r, ) = BatchProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedBatchProof(uint256 p, bytes memory bs) + internal + pure + returns (CompressedBatchProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedBatchProof.Data memory r, ) = CompressedBatchProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += BatchProof._encode_nested(r.batch, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedBatchProof._encode_nested(r.compressed, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); + e += 1 + ProtoBufRuntime._sz_lendelim(BatchProof._estimate(r.batch)); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchProof._estimate(r.compressed)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + ExistenceProof.store(input.exist, output.exist); + NonExistenceProof.store(input.nonexist, output.nonexist); + BatchProof.store(input.batch, output.batch); + CompressedBatchProof.store(input.compressed, output.compressed); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CommitmentProof + +library LeafOp { + + + //struct definition + struct Data { + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; + PROOFS_PROTO_GLOBAL_ENUMS.HashOp prehash_key; + PROOFS_PROTO_GLOBAL_ENUMS.HashOp prehash_value; + PROOFS_PROTO_GLOBAL_ENUMS.LengthOp length; + bytes prefix; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[6] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_hash(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_prehash_key(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_prehash_value(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_length(pointer, bs, r, counters); + } + else if (fieldId == 5) { + pointer += _read_prefix(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[1] += 1; + } else { + r.hash = x; + if(counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prehash_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[2] += 1; + } else { + r.prehash_key = x; + if(counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prehash_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[3] += 1; + } else { + r.prehash_value = x; + if(counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_length( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.LengthOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_LengthOp(tmp); + if (isNil(r)) { + counters[4] += 1; + } else { + r.length = x; + if(counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prefix( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.prefix = x; + if (counters[5] > 0) counters[5] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + if (uint(r.hash) != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); + pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); + } + if (uint(r.prehash_key) != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_prehash_key = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_key); + pointer += ProtoBufRuntime._encode_enum(_enum_prehash_key, pointer, bs); + } + if (uint(r.prehash_value) != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_prehash_value = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_value); + pointer += ProtoBufRuntime._encode_enum(_enum_prehash_value, pointer, bs); + } + if (uint(r.length) != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_length = PROOFS_PROTO_GLOBAL_ENUMS.encode_LengthOp(r.length); + pointer += ProtoBufRuntime._encode_enum(_enum_length, pointer, bs); + } + if (r.prefix.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 5, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.prefix, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_key)); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_value)); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_LengthOp(r.length)); + e += 1 + ProtoBufRuntime._sz_lendelim(r.prefix.length); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (uint(r.hash) != 0) { + return false; + } + + if (uint(r.prehash_key) != 0) { + return false; + } + + if (uint(r.prehash_value) != 0) { + return false; + } + + if (uint(r.length) != 0) { + return false; + } + + if (r.prefix.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.hash = input.hash; + output.prehash_key = input.prehash_key; + output.prehash_value = input.prehash_value; + output.length = input.length; + output.prefix = input.prefix; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library LeafOp + +library InnerOp { + + + //struct definition + struct Data { + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; + bytes prefix; + bytes suffix; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[4] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_hash(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_prefix(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_suffix(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[1] += 1; + } else { + r.hash = x; + if(counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prefix( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.prefix = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_suffix( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.suffix = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + if (uint(r.hash) != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); + pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); + } + if (r.prefix.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.prefix, pointer, bs); + } + if (r.suffix.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.suffix, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); + e += 1 + ProtoBufRuntime._sz_lendelim(r.prefix.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.suffix.length); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (uint(r.hash) != 0) { + return false; + } + + if (r.prefix.length != 0) { + return false; + } + + if (r.suffix.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.hash = input.hash; + output.prefix = input.prefix; + output.suffix = input.suffix; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library InnerOp + +library ProofSpec { + + + //struct definition + struct Data { + LeafOp.Data leaf_spec; + InnerSpec.Data inner_spec; + int32 max_depth; + int32 min_depth; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_leaf_spec(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_inner_spec(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_max_depth(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_min_depth(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_leaf_spec( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.leaf_spec = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_inner_spec( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (InnerSpec.Data memory x, uint256 sz) = _decode_InnerSpec(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.inner_spec = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_max_depth( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.max_depth = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_min_depth( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.min_depth = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_LeafOp(uint256 p, bytes memory bs) + internal + pure + returns (LeafOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_InnerSpec(uint256 p, bytes memory bs) + internal + pure + returns (InnerSpec.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (InnerSpec.Data memory r, ) = InnerSpec._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += LeafOp._encode_nested(r.leaf_spec, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += InnerSpec._encode_nested(r.inner_spec, pointer, bs); + + if (r.max_depth != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.max_depth, pointer, bs); + } + if (r.min_depth != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.min_depth, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf_spec)); + e += 1 + ProtoBufRuntime._sz_lendelim(InnerSpec._estimate(r.inner_spec)); + e += 1 + ProtoBufRuntime._sz_int32(r.max_depth); + e += 1 + ProtoBufRuntime._sz_int32(r.min_depth); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.max_depth != 0) { + return false; + } + + if (r.min_depth != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + LeafOp.store(input.leaf_spec, output.leaf_spec); + InnerSpec.store(input.inner_spec, output.inner_spec); + output.max_depth = input.max_depth; + output.min_depth = input.min_depth; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library ProofSpec + +library InnerSpec { + + + //struct definition + struct Data { + int32[] child_order; + int32 child_size; + int32 min_prefix_length; + int32 max_prefix_length; + bytes empty_child; + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[7] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_child_order(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_child_size(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_min_prefix_length(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_max_prefix_length(pointer, bs, r, counters); + } + else if (fieldId == 5) { + pointer += _read_empty_child(pointer, bs, r, counters); + } + else if (fieldId == 6) { + pointer += _read_hash(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.child_order = new int32[](counters[1]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_child_order(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_child_size(pointer, bs, nil(), counters); + } + else if (fieldId == 3) { + pointer += _read_min_prefix_length(pointer, bs, nil(), counters); + } + else if (fieldId == 4) { + pointer += _read_max_prefix_length(pointer, bs, nil(), counters); + } + else if (fieldId == 5) { + pointer += _read_empty_child(pointer, bs, nil(), counters); + } + else if (fieldId == 6) { + pointer += _read_hash(pointer, bs, nil(), counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_child_order( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.child_order[r.child_order.length - counters[1]] = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_child_size( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.child_size = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_min_prefix_length( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.min_prefix_length = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_max_prefix_length( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.max_prefix_length = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_empty_child( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.empty_child = x; + if (counters[5] > 0) counters[5] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[6] += 1; + } else { + r.hash = x; + if(counters[6] > 0) counters[6] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.child_order.length != 0) { + for(i = 0; i < r.child_order.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.Varint, + pointer, + bs) + ; + pointer += ProtoBufRuntime._encode_int32(r.child_order[i], pointer, bs); + } + } + if (r.child_size != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.child_size, pointer, bs); + } + if (r.min_prefix_length != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.min_prefix_length, pointer, bs); + } + if (r.max_prefix_length != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.max_prefix_length, pointer, bs); + } + if (r.empty_child.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 5, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.empty_child, pointer, bs); + } + if (uint(r.hash) != 0) { + pointer += ProtoBufRuntime._encode_key( + 6, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); + pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + for(i = 0; i < r.child_order.length; i++) { + e += 1 + ProtoBufRuntime._sz_int32(r.child_order[i]); + } + e += 1 + ProtoBufRuntime._sz_int32(r.child_size); + e += 1 + ProtoBufRuntime._sz_int32(r.min_prefix_length); + e += 1 + ProtoBufRuntime._sz_int32(r.max_prefix_length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.empty_child.length); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.child_order.length != 0) { + return false; + } + + if (r.child_size != 0) { + return false; + } + + if (r.min_prefix_length != 0) { + return false; + } + + if (r.max_prefix_length != 0) { + return false; + } + + if (r.empty_child.length != 0) { + return false; + } + + if (uint(r.hash) != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.child_order = input.child_order; + output.child_size = input.child_size; + output.min_prefix_length = input.min_prefix_length; + output.max_prefix_length = input.max_prefix_length; + output.empty_child = input.empty_child; + output.hash = input.hash; + + } + + + //array helpers for ChildOrder + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addChildOrder(Data memory self, int32 value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + int32[] memory tmp = new int32[](self.child_order.length + 1); + for (uint256 i = 0; i < self.child_order.length; i++) { + tmp[i] = self.child_order[i]; + } + tmp[self.child_order.length] = value; + self.child_order = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library InnerSpec + +library BatchProof { + + + //struct definition + struct Data { + BatchEntry.Data[] entries; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[2] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.entries = new BatchEntry.Data[](counters[1]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_entries( + uint256 p, + bytes memory bs, + Data memory r, + uint[2] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (BatchEntry.Data memory x, uint256 sz) = _decode_BatchEntry(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.entries[r.entries.length - counters[1]] = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_BatchEntry(uint256 p, bytes memory bs) + internal + pure + returns (BatchEntry.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (BatchEntry.Data memory r, ) = BatchEntry._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.entries.length != 0) { + for(i = 0; i < r.entries.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += BatchEntry._encode_nested(r.entries[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + for(i = 0; i < r.entries.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(BatchEntry._estimate(r.entries[i])); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.entries.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + + for(uint256 i1 = 0; i1 < input.entries.length; i1++) { + output.entries.push(input.entries[i1]); + } + + + } + + + //array helpers for Entries + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addEntries(Data memory self, BatchEntry.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + BatchEntry.Data[] memory tmp = new BatchEntry.Data[](self.entries.length + 1); + for (uint256 i = 0; i < self.entries.length; i++) { + tmp[i] = self.entries[i]; + } + tmp[self.entries.length] = value; + self.entries = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library BatchProof + +library BatchEntry { + + + //struct definition + struct Data { + ExistenceProof.Data exist; + NonExistenceProof.Data nonexist; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_exist(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.exist = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_nonexist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.nonexist = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (ExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_NonExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (NonExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + ExistenceProof.store(input.exist, output.exist); + NonExistenceProof.store(input.nonexist, output.nonexist); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library BatchEntry + +library CompressedBatchProof { + + + //struct definition + struct Data { + CompressedBatchEntry.Data[] entries; + InnerOp.Data[] lookup_inners; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_lookup_inners(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.entries = new CompressedBatchEntry.Data[](counters[1]); + r.lookup_inners = new InnerOp.Data[](counters[2]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_lookup_inners(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_entries( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedBatchEntry.Data memory x, uint256 sz) = _decode_CompressedBatchEntry(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.entries[r.entries.length - counters[1]] = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_lookup_inners( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.lookup_inners[r.lookup_inners.length - counters[2]] = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedBatchEntry(uint256 p, bytes memory bs) + internal + pure + returns (CompressedBatchEntry.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedBatchEntry.Data memory r, ) = CompressedBatchEntry._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_InnerOp(uint256 p, bytes memory bs) + internal + pure + returns (InnerOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.entries.length != 0) { + for(i = 0; i < r.entries.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += CompressedBatchEntry._encode_nested(r.entries[i], pointer, bs); + } + } + if (r.lookup_inners.length != 0) { + for(i = 0; i < r.lookup_inners.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += InnerOp._encode_nested(r.lookup_inners[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + for(i = 0; i < r.entries.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchEntry._estimate(r.entries[i])); + } + for(i = 0; i < r.lookup_inners.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.lookup_inners[i])); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.entries.length != 0) { + return false; + } + + if (r.lookup_inners.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + + for(uint256 i1 = 0; i1 < input.entries.length; i1++) { + output.entries.push(input.entries[i1]); + } + + + for(uint256 i2 = 0; i2 < input.lookup_inners.length; i2++) { + output.lookup_inners.push(input.lookup_inners[i2]); + } + + + } + + + //array helpers for Entries + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addEntries(Data memory self, CompressedBatchEntry.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + CompressedBatchEntry.Data[] memory tmp = new CompressedBatchEntry.Data[](self.entries.length + 1); + for (uint256 i = 0; i < self.entries.length; i++) { + tmp[i] = self.entries[i]; + } + tmp[self.entries.length] = value; + self.entries = tmp; + } + + //array helpers for LookupInners + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addLookupInners(Data memory self, InnerOp.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + InnerOp.Data[] memory tmp = new InnerOp.Data[](self.lookup_inners.length + 1); + for (uint256 i = 0; i < self.lookup_inners.length; i++) { + tmp[i] = self.lookup_inners[i]; + } + tmp[self.lookup_inners.length] = value; + self.lookup_inners = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CompressedBatchProof + +library CompressedBatchEntry { + + + //struct definition + struct Data { + CompressedExistenceProof.Data exist; + CompressedNonExistenceProof.Data nonexist; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_exist(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.exist = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_nonexist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedNonExistenceProof.Data memory x, uint256 sz) = _decode_CompressedNonExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.nonexist = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (CompressedExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedNonExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (CompressedNonExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedNonExistenceProof.Data memory r, ) = CompressedNonExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedNonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedNonExistenceProof._estimate(r.nonexist)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + CompressedExistenceProof.store(input.exist, output.exist); + CompressedNonExistenceProof.store(input.nonexist, output.nonexist); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CompressedBatchEntry + +library CompressedExistenceProof { + + + //struct definition + struct Data { + bytes key; + bytes value; + LeafOp.Data leaf; + int32[] path; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.path = new int32[](counters[4]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, nil(), counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, nil(), counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.value = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_leaf( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.leaf = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_path( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.path[r.path.length - counters[4]] = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_LeafOp(uint256 p, bytes memory bs) + internal + pure + returns (LeafOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + if (r.value.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += LeafOp._encode_nested(r.leaf, pointer, bs); + + if (r.path.length != 0) { + for(i = 0; i < r.path.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs) + ; + pointer += ProtoBufRuntime._encode_int32(r.path[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); + for(i = 0; i < r.path.length; i++) { + e += 1 + ProtoBufRuntime._sz_int32(r.path[i]); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + if (r.value.length != 0) { + return false; + } + + if (r.path.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + output.value = input.value; + LeafOp.store(input.leaf, output.leaf); + output.path = input.path; + + } + + + //array helpers for Path + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addPath(Data memory self, int32 value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + int32[] memory tmp = new int32[](self.path.length + 1); + for (uint256 i = 0; i < self.path.length; i++) { + tmp[i] = self.path[i]; + } + tmp[self.path.length] = value; + self.path = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CompressedExistenceProof + +library CompressedNonExistenceProof { + + + //struct definition + struct Data { + bytes key; + CompressedExistenceProof.Data left; + CompressedExistenceProof.Data right; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[4] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_left(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_right(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_left( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.left = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_right( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.right = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (CompressedExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedExistenceProof._encode_nested(r.left, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedExistenceProof._encode_nested(r.right, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + /** + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.right)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + CompressedExistenceProof.store(input.left, output.left); + CompressedExistenceProof.store(input.right, output.right); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CompressedNonExistenceProof + +library PROOFS_PROTO_GLOBAL_ENUMS { + + //enum definition + // Solidity enum definitions + enum HashOp { + NO_HASH, + SHA256, + SHA512, + KECCAK, + RIPEMD160, + BITCOIN, + SHA512_256 + } + + + // Solidity enum encoder + function encode_HashOp(HashOp x) internal pure returns (int32) { + + if (x == HashOp.NO_HASH) { + return 0; + } + + if (x == HashOp.SHA256) { + return 1; + } + + if (x == HashOp.SHA512) { + return 2; + } + + if (x == HashOp.KECCAK) { + return 3; + } + + if (x == HashOp.RIPEMD160) { + return 4; + } + + if (x == HashOp.BITCOIN) { + return 5; + } + + if (x == HashOp.SHA512_256) { + return 6; + } + revert(); + } + + + // Solidity enum decoder + function decode_HashOp(int64 x) internal pure returns (HashOp) { + + if (x == 0) { + return HashOp.NO_HASH; + } + + if (x == 1) { + return HashOp.SHA256; + } + + if (x == 2) { + return HashOp.SHA512; + } + + if (x == 3) { + return HashOp.KECCAK; + } + + if (x == 4) { + return HashOp.RIPEMD160; + } + + if (x == 5) { + return HashOp.BITCOIN; + } + + if (x == 6) { + return HashOp.SHA512_256; + } + revert(); + } + + + // Solidity enum definitions + enum LengthOp { + NO_PREFIX, + VAR_PROTO, + VAR_RLP, + FIXED32_BIG, + FIXED32_LITTLE, + FIXED64_BIG, + FIXED64_LITTLE, + REQUIRE_32_BYTES, + REQUIRE_64_BYTES + } + + + // Solidity enum encoder + function encode_LengthOp(LengthOp x) internal pure returns (int32) { + + if (x == LengthOp.NO_PREFIX) { + return 0; + } + + if (x == LengthOp.VAR_PROTO) { + return 1; + } + + if (x == LengthOp.VAR_RLP) { + return 2; + } + + if (x == LengthOp.FIXED32_BIG) { + return 3; + } + + if (x == LengthOp.FIXED32_LITTLE) { + return 4; + } + + if (x == LengthOp.FIXED64_BIG) { + return 5; + } + + if (x == LengthOp.FIXED64_LITTLE) { + return 6; + } + + if (x == LengthOp.REQUIRE_32_BYTES) { + return 7; + } + + if (x == LengthOp.REQUIRE_64_BYTES) { + return 8; + } + revert(); + } + + + // Solidity enum decoder + function decode_LengthOp(int64 x) internal pure returns (LengthOp) { + + if (x == 0) { + return LengthOp.NO_PREFIX; + } + + if (x == 1) { + return LengthOp.VAR_PROTO; + } + + if (x == 2) { + return LengthOp.VAR_RLP; + } + + if (x == 3) { + return LengthOp.FIXED32_BIG; + } + + if (x == 4) { + return LengthOp.FIXED32_LITTLE; + } + + if (x == 5) { + return LengthOp.FIXED64_BIG; + } + + if (x == 6) { + return LengthOp.FIXED64_LITTLE; + } + + if (x == 7) { + return LengthOp.REQUIRE_32_BYTES; + } + + if (x == 8) { + return LengthOp.REQUIRE_64_BYTES; + } + revert(); + } + +} +//library PROOFS_PROTO_GLOBAL_ENUMS diff --git a/sol/package-lock.json b/sol/package-lock.json new file mode 100644 index 00000000..2a74b195 --- /dev/null +++ b/sol/package-lock.json @@ -0,0 +1,680 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "ganache-cli": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.12.2.tgz", + "integrity": "sha512-bnmwnJDBDsOWBUP8E/BExWf85TsdDEFelQSzihSJm9VChVO1SHp94YXLP5BlA4j/OTxp0wR4R1Tje9OHOuAJVw==", + "requires": { + "ethereumjs-util": "6.2.1", + "source-map-support": "0.5.12", + "yargs": "13.2.4" + }, + "dependencies": { + "@types/bn.js": { + "version": "4.11.6", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node": { + "version": "14.11.2", + "bundled": true + }, + "@types/pbkdf2": { + "version": "3.1.0", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "@types/secp256k1": { + "version": "4.0.1", + "bundled": true, + "requires": { + "@types/node": "*" + } + }, + "ansi-regex": { + "version": "4.1.0", + "bundled": true + }, + "ansi-styles": { + "version": "3.2.1", + "bundled": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "base-x": { + "version": "3.0.8", + "bundled": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "blakejs": { + "version": "1.1.0", + "bundled": true + }, + "bn.js": { + "version": "4.11.9", + "bundled": true + }, + "brorand": { + "version": "1.1.0", + "bundled": true + }, + "browserify-aes": { + "version": "1.2.0", + "bundled": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "bs58": { + "version": "4.0.1", + "bundled": true, + "requires": { + "base-x": "^3.0.2" + } + }, + "bs58check": { + "version": "2.1.2", + "bundled": true, + "requires": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "buffer-from": { + "version": "1.1.1", + "bundled": true + }, + "buffer-xor": { + "version": "1.0.3", + "bundled": true + }, + "camelcase": { + "version": "5.3.1", + "bundled": true + }, + "cipher-base": { + "version": "1.0.4", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cliui": { + "version": "5.0.0", + "bundled": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "bundled": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "bundled": true + }, + "create-hash": { + "version": "1.2.0", + "bundled": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "bundled": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "elliptic": { + "version": "6.5.3", + "bundled": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "bundled": true + }, + "end-of-stream": { + "version": "1.4.4", + "bundled": true, + "requires": { + "once": "^1.4.0" + } + }, + "ethereum-cryptography": { + "version": "0.1.3", + "bundled": true, + "requires": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "ethereumjs-util": { + "version": "6.2.1", + "bundled": true, + "requires": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "ethjs-util": { + "version": "0.1.6", + "bundled": true, + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "bundled": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "bundled": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "bundled": true + }, + "get-stream": { + "version": "4.1.0", + "bundled": true, + "requires": { + "pump": "^3.0.0" + } + }, + "hash-base": { + "version": "3.1.0", + "bundled": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "hash.js": { + "version": "1.1.7", + "bundled": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "bundled": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true + }, + "invert-kv": { + "version": "2.0.0", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true + }, + "is-hex-prefixed": { + "version": "1.0.0", + "bundled": true + }, + "is-stream": { + "version": "1.1.0", + "bundled": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true + }, + "keccak": { + "version": "3.0.1", + "bundled": true, + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "lcid": { + "version": "2.0.0", + "bundled": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "bundled": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "4.3.0", + "bundled": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "bundled": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "bundled": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true + }, + "node-addon-api": { + "version": "2.0.2", + "bundled": true + }, + "node-gyp-build": { + "version": "4.2.3", + "bundled": true + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1" + } + }, + "os-locale": { + "version": "3.1.0", + "bundled": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, + "p-finally": { + "version": "1.0.0", + "bundled": true + }, + "p-is-promise": { + "version": "2.1.0", + "bundled": true + }, + "p-limit": { + "version": "2.3.0", + "bundled": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "bundled": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "bundled": true + }, + "path-exists": { + "version": "3.0.0", + "bundled": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true + }, + "pbkdf2": { + "version": "3.1.1", + "bundled": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pump": { + "version": "3.0.0", + "bundled": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "randombytes": { + "version": "2.1.0", + "bundled": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "bundled": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true + }, + "require-main-filename": { + "version": "2.0.0", + "bundled": true + }, + "ripemd160": { + "version": "2.0.2", + "bundled": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rlp": { + "version": "2.2.6", + "bundled": true, + "requires": { + "bn.js": "^4.11.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "bundled": true + }, + "scrypt-js": { + "version": "3.0.1", + "bundled": true + }, + "secp256k1": { + "version": "4.0.2", + "bundled": true, + "requires": { + "elliptic": "^6.5.2", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + } + }, + "semver": { + "version": "5.7.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "setimmediate": { + "version": "1.0.5", + "bundled": true + }, + "sha.js": { + "version": "2.4.11", + "bundled": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.3", + "bundled": true + }, + "source-map": { + "version": "0.6.1", + "bundled": true + }, + "source-map-support": { + "version": "0.5.12", + "bundled": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "string-width": { + "version": "3.1.0", + "bundled": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "bundled": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true + }, + "strip-hex-prefix": { + "version": "1.0.0", + "bundled": true, + "requires": { + "is-hex-prefixed": "1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "which": { + "version": "1.3.1", + "bundled": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true + }, + "wrap-ansi": { + "version": "5.1.0", + "bundled": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + }, + "y18n": { + "version": "4.0.0", + "bundled": true + }, + "yargs": { + "version": "13.2.4", + "bundled": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "yargs-parser": { + "version": "13.1.2", + "bundled": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + } + } +} diff --git a/sol/tests/convert.py b/sol/tests/convert.py new file mode 100644 index 00000000..c8a0faf9 --- /dev/null +++ b/sol/tests/convert.py @@ -0,0 +1,51 @@ +from brownie.convert import to_bytes +import base64 + +def leafOp(leafOp): + if leafOp is None: + return (0, 0, 0, 0, b'') + return (leafOp.get("hash", 0), + leafOp.get("prehash_key", 0), + leafOp.get("prehash_value", 0), + leafOp.get("length", 0), + base64.b64decode(leafOp.get("prefix", "")) + ) + + +def innerOp(innerOp): + if innerOp is None: + return (0, b'', b'') + return (innerOp.get("hash", 0), + base64.b64decode(innerOp.get("prefix", "")), + base64.b64decode(innerOp.get("suffix", "")), + ) + + +def existenceProof(exProof): + return (base64.b64decode(exProof.get("key", "")), + base64.b64decode(exProof.get("value", "")), + leafOp(exProof.get("leaf")), + [innerOp(op_elem) for op_elem in exProof.get("path", [])], + ) + + +def innerSpec(innerSpec): + if innerSpec is None: + return([], 0, 0, 0, b'', 0) + return ([el for el in innerSpec.get("child_order", [])], + innerSpec.get("child_size", 0), + innerSpec.get("min_prefix_length", 0), + innerSpec.get("max_prefix_length", 0), + base64.b64decode(innerSpec.get("empty_child", "")), + innerSpec.get("hash", 0), + ) + + +def proofSpec(proofSpec): + if proofSpec is None: + return (leafOp(None), innerSpec(None), 0, 0) + return (leafOp(proofSpec.get("leaf_spec", None)), + innerSpec(proofSpec.get("inner_spec", None)), + proofSpec.get("max_depth", 0), + proofSpec.get("min_depth", 0), + ) diff --git a/sol/tests/helpers.py b/sol/tests/helpers.py new file mode 100644 index 00000000..fe9097b5 --- /dev/null +++ b/sol/tests/helpers.py @@ -0,0 +1,34 @@ +import json +from brownie.convert import to_bytes + + +def loadFile(f, contract): + case = json.load(f) + refData = { + "rootHash": to_bytes(case.get("root", b''), "bytes"), + "key": to_bytes(case.get("key", b''), "bytes"), + "value": None if case.get("value", "") == "" else to_bytes(case["value"], "bytes"), + } + proof = contract.protobufDecodeCommitmentProof(to_bytes(case.get("proof", b''), "bytes")) + return proof, refData + + +def loadBatchFile(f, contract): + case = json.load(f) + refData = { + "rootHash": to_bytes(case.get("root", b''), "bytes"), + "items": [(to_bytes(item["key"], "bytes"), + None if item.get("value", "") == "" else to_bytes(item["value"], "bytes")) + for item in case["items"] + ] + } + print(to_bytes(case.get("proof", b''), "bytes")) + proof = contract.protobufDecodeCommitmentProof(to_bytes(case.get("proof", b''), "bytes")) + return proof, refData + + +def loadJsonTestCases(fname): + with open(fname) as f: + testcases = json.load(f) + cases = [ (name, testcases[name]) for name in testcases] + return cases diff --git a/sol/tests/specs.py b/sol/tests/specs.py new file mode 100644 index 00000000..f43c5f0e --- /dev/null +++ b/sol/tests/specs.py @@ -0,0 +1,12 @@ + +iavl = ( + (1, 0, 1, 1, b'\x00'), #leafOp + ([0,1], 33, 4, 12, b'', 1), #innerSpec + 0, 0, + ) + +tendermint = ( + (1, 0, 1, 1, b'\x00'), #leafOp + ([0,1], 32, 1, 1, b'', 1), #innerSpec + 0, 0, + ) diff --git a/sol/tests/test_ics23compress.py b/sol/tests/test_ics23compress.py new file mode 100644 index 00000000..74b73bd7 --- /dev/null +++ b/sol/tests/test_ics23compress.py @@ -0,0 +1,37 @@ +from brownie import accounts, Compress_UnitTest, Proof_UnitTest +from brownie.convert import to_bytes +import pytest +import specs +import os +import helpers + + +IAVL_TEST_DIR = "../testdata/iavl" +TENDERMINT_TEST_DIR = "../testdata/tendermint" +cases_fname = ["batch_exist.json", "batch_nonexist.json"] + + +@pytest.fixture +def compress(): + return accounts[0].deploy(Compress_UnitTest) + + +@pytest.fixture +def proof(): + return accounts[0].deploy(Proof_UnitTest) + + +@pytest.mark.parametrize("fname", [os.path.join(IAVL_TEST_DIR, fname) for fname in cases_fname]) +@pytest.mark.skip(reason="potential bug in ProtobufRuntime") +def test_iavl_decompress(compress, proof, fname): + proofSpec = specs.iavl + with open(fname) as f: + comProof, refData = helpers.loadBatchFile(f, proof) + + +@pytest.mark.parametrize("fname", [os.path.join(TENDERMINT_TEST_DIR, fname) for fname in cases_fname]) +@pytest.mark.skip(reason="potential bug in ProtobufRuntime") +def test_tendermint_decompress(compress, proof, fname): + proofSpec = specs.tendermint + with open(fname) as f: + comProof, refData = helpers.loadBatchFile(f, proof) diff --git a/sol/tests/test_ics23ops.py b/sol/tests/test_ics23ops.py new file mode 100644 index 00000000..5ca57c43 --- /dev/null +++ b/sol/tests/test_ics23ops.py @@ -0,0 +1,62 @@ +from brownie import accounts, Ops_UnitTest +from brownie.convert import to_bytes, to_string +import brownie +import pytest +import convert +import base64 +import helpers + + +@pytest.fixture +def ops(): + return accounts[0].deploy(Ops_UnitTest) + + +@pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestLeafOpData.json")) +def test_leafOp(ops, name, case): + if "sha-512" in name: + pytest.skip("sha-512 not supported in solidity") + opCase = convert.leafOp(case["Op"]) + key = base64.b64decode(case["Key"] or "") + value = base64.b64decode(case["Value"] or "") + if case["IsErr"]: + with brownie.reverts(): + res = ops.applyLeafOp(opCase, key, value) + else: + res = ops.applyLeafOp(opCase, key, value) + expected = base64.b64decode(case["Expected"]) + assert to_bytes(res, "bytes") == expected, name + + +@pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestInnerOpData.json")) +def test_inner_op(ops, name, case): + opCase = convert.innerOp(case["Op"]) + child = base64.b64decode(case["Child"] or "") + if case["IsErr"]: + with brownie.reverts(): + res = ops.applyInnerOp(opCase, child) + else: + res = ops.applyInnerOp(opCase, child) + expected = base64.b64decode(case["Expected"]) + assert to_bytes(res, "bytes") == expected, name + + +@pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestDoHashData.json")) +def test_do_hash(ops, name, case): + if "sha512" in name: # sha-512 not supported in solidity + pytest.skip("sha-512 not supported in solidity") + preImage = case["Preimage"].encode() + res = ops.doHash(case["HashOp"], preImage) + expected = to_bytes(case["ExpectedHash"], "bytes") + assert to_bytes(res, "bytes") == expected, name + + +@pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestCheckLeafData.json")) +def test_check_leaf(ops, name, case): + leafOp = convert.leafOp(case.get("Leaf", None)) + proofSpec = (convert.leafOp(case.get("Spec", None)), convert.innerSpec(None), 0, 0) + if case["IsErr"]: + with brownie.reverts(): + res = ops.checkAgainstLeafOpSpec(leafOp, proofSpec) + else: + res = ops.checkAgainstLeafOpSpec(leafOp, proofSpec) diff --git a/sol/tests/test_ics23proof.py b/sol/tests/test_ics23proof.py new file mode 100644 index 00000000..af89e59c --- /dev/null +++ b/sol/tests/test_ics23proof.py @@ -0,0 +1,35 @@ +from brownie import accounts, Proof_UnitTest +from brownie.convert import to_bytes, to_string +import brownie +import pytest +import convert +import base64 +import helpers + + +@pytest.fixture +def proof(): + return accounts[0].deploy(Proof_UnitTest) + + +@pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestExistenceProofData.json")) +def test_existence_proof(proof, name, case): + exProof = convert.existenceProof(case["Proof"]) + if case["IsErr"]: + with brownie.reverts(): + res = proof.calculateExistenceProofRoot(exProof) + else: + res = proof.calculateExistenceProofRoot(exProof) + expected = base64.b64decode(case["Expected"]) + assert to_bytes(res, "bytes") == expected, name + + +@pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestCheckAgainstSpecData.json")) +def test_checkagainstspec(proof, name, case): + exProof = convert.existenceProof(case["Proof"]) + spec = convert.proofSpec(case["Spec"]) + if case["IsErr"]: + with brownie.reverts(): + proof.checkAgainstSpec(exProof, spec) + else: + proof.checkAgainstSpec(exProof, spec) diff --git a/sol/tests/test_ics23vectors.py b/sol/tests/test_ics23vectors.py new file mode 100644 index 00000000..21e84d20 --- /dev/null +++ b/sol/tests/test_ics23vectors.py @@ -0,0 +1,47 @@ +from brownie import accounts, ICS23_UnitTest, Proof_UnitTest +from brownie.convert import to_bytes +import pytest +import specs +import os +import helpers + + +IAVL_TEST_DIR = "../testdata/iavl" +TENDERMINT_TEST_DIR = "../testdata/tendermint" +cases_fname = ["exist_left.json","exist_right.json", "exist_middle.json", "nonexist_left.json", "nonexist_right.json", "nonexist_middle.json"] + + +@pytest.fixture +def ics23(): + return accounts[0].deploy(ICS23_UnitTest) + + +@pytest.fixture +def proof(): + return accounts[0].deploy(Proof_UnitTest) + + +@pytest.mark.parametrize("fname", [os.path.join(IAVL_TEST_DIR, fname) for fname in cases_fname]) +def test_iavl_vectors(ics23, proof, fname): + proofSpec = specs.iavl + with open(fname) as f: + comProof, refData = helpers.loadFile(f, proof) + calculatedRoot = to_bytes(proof.calculateCommitmentProofRoot(comProof), "bytes") + assert refData["rootHash"] == calculatedRoot, completeFname + if not refData["value"]: + ics23.verifyNonMembership(proofSpec, refData["rootHash"], comProof, refData["key"]) + else: + ics23.verifyMembership(proofSpec, refData["rootHash"], comProof, refData["key"], refData["value"]) + + +@pytest.mark.parametrize("fname", [os.path.join(TENDERMINT_TEST_DIR, fname) for fname in cases_fname]) +def test_tendermint_vectors(ics23, proof, fname): + proofSpec = specs.tendermint + with open(fname) as f: + comProof, refData = helpers.loadFile(f, proof) + calculatedRoot = to_bytes(proof.calculateCommitmentProofRoot(comProof), "bytes") + assert refData["rootHash"] == calculatedRoot, completeFname + if not refData["value"]: + ics23.verifyNonMembership(proofSpec, refData["rootHash"], comProof, refData["key"]) + else: + ics23.verifyMembership(proofSpec, refData["rootHash"], comProof, refData["key"], refData["value"]) From 67821e5bf2ed58b3adff47dd13778a7aad1bf887 Mon Sep 17 00:00:00 2001 From: Giulio Date: Fri, 10 Dec 2021 09:25:43 +0100 Subject: [PATCH 2/7] first partial round of review --- sol/contracts/ics23Compress.sol | 9 +++++++++ sol/contracts/ics23Ops.sol | 8 ++++---- sol/contracts/ics23Proof.sol | 1 - 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/sol/contracts/ics23Compress.sol b/sol/contracts/ics23Compress.sol index 66d04f37..173934f3 100644 --- a/sol/contracts/ics23Compress.sol +++ b/sol/contracts/ics23Compress.sol @@ -65,3 +65,12 @@ library Compress { return decoProof; } } + + + + +contract Compress_UnitTest { + function decompress(CommitmentProof.Data memory proof) public pure returns(CommitmentProof.Data memory) { + return Compress.decompress(proof); + } +} diff --git a/sol/contracts/ics23Ops.sol b/sol/contracts/ics23Ops.sol index c09c597d..2b08e64f 100644 --- a/sol/contracts/ics23Ops.sol +++ b/sol/contracts/ics23Ops.sol @@ -15,7 +15,7 @@ library Ops { require(value.length > 0); // dev: Leaf op needs value bytes memory pKey = prepareLeafData(leafOp.prehash_key, leafOp.length, key); bytes memory pValue = prepareLeafData(leafOp.prehash_value, leafOp.length, value); - bytes memory data = bytes.concat(leafOp.prefix, pKey, pValue); + bytes memory data = abi.encodePacked(leafOp.prefix, pKey, pValue); return doHash(leafOp.hash, data); } function prepareLeafData(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) internal pure returns(bytes memory) { @@ -34,7 +34,7 @@ library Ops { // InnerOp operations function applyOp(InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory) { require(child.length > 0); // dev: Inner op needs child value - bytes memory preImage = bytes.concat(innerOp.prefix, child, innerOp.suffix); + bytes memory preImage = abi.encodePacked(innerOp.prefix, child, innerOp.suffix); return doHash(innerOp.hash, preImage); } function checkAgainstSpec(InnerOp.Data memory innerOp, ProofSpec.Data memory spec) internal pure { @@ -107,7 +107,7 @@ library Ops { uint256 sz = ProtoBufRuntime._sz_varint(data.length); bytes memory encoded = new bytes(sz); ProtoBufRuntime._encode_varint(data.length, 32, encoded); - return bytes.concat(encoded, data); + return abi.encodePacked(encoded, data); } if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.REQUIRE_32_BYTES) { require(data.length == 32); // dev: data.length != 32 @@ -127,7 +127,7 @@ library Ops { littleE[1] = sizeB[2]; littleE[2] = sizeB[1]; littleE[3] = sizeB[0]; - return bytes.concat(littleE, data); + return abi.encodePacked(littleE, data); } revert(); // dev: Unsupported lenOp } diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol index 6a4f41b8..82c849a4 100644 --- a/sol/contracts/ics23Proof.sol +++ b/sol/contracts/ics23Proof.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -pragma experimental ABIEncoderV2; import {LeafOp, CompressedBatchProof, ExistenceProof, NonExistenceProof, BatchEntry, BatchProof, ProofSpec, InnerOp, InnerSpec, CommitmentProof} from "./proofs.sol"; import {Ops} from "./ics23Ops.sol"; From 725563fba25349ed8e69834a67dffe22180ac21a Mon Sep 17 00:00:00 2001 From: Giulio Date: Tue, 14 Dec 2021 09:17:15 +0100 Subject: [PATCH 3/7] 2nd round of reviews Changing the return values of functions throughout the libraries to avoid using ``require`` and ``revert``. Function callers will receive an enum encoding the Error --- sol/contracts/ics23.sol | 36 +- sol/contracts/ics23Ops.sol | 183 +- sol/contracts/ics23Proof.sol | 223 +- sol/contracts/proofs.sol | 10336 ++++++++++++++++----------------- sol/tests/helpers.py | 1 - 5 files changed, 5494 insertions(+), 5285 deletions(-) diff --git a/sol/contracts/ics23.sol b/sol/contracts/ics23.sol index 6a670c49..16e041f5 100644 --- a/sol/contracts/ics23.sol +++ b/sol/contracts/ics23.sol @@ -8,19 +8,37 @@ import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol" library Ics23 { + enum VerifyMembershipError { + None, + ExistenceProofIsNil, + ProofVerify + } // verifyMembership, throws an exception in case anything goes wrong - function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) internal pure { + function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) internal pure returns(VerifyMembershipError){ CommitmentProof.Data memory decoProof = Compress.decompress(proof); ExistenceProof.Data memory exiProof = getExistProofForKey(decoProof, key); - require(ExistenceProof.isNil(exiProof) == false); // dev: getExistProofForKey not available - Proof.verify(exiProof, spec, commitmentRoot, key, value); + //require(ExistenceProof.isNil(exiProof) == false); // dev: getExistProofForKey not available + if (ExistenceProof.isNil(exiProof)) return VerifyMembershipError.ExistenceProofIsNil; + Proof.VerifyExistenceError vCode = Proof.verify(exiProof, spec, commitmentRoot, key, value); + if (vCode != Proof.VerifyExistenceError.None) return VerifyMembershipError.ProofVerify; + + return VerifyMembershipError.None; } - function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) internal pure { + enum VerifyNonMembershipError { + None, + NonExistenceProofIsNil, + ProofVerify + } + function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) internal pure returns(VerifyNonMembershipError) { CommitmentProof.Data memory decoProof = Compress.decompress(proof); NonExistenceProof.Data memory nonProof = getNonExistProofForKey(decoProof, key); - require(NonExistenceProof.isNil(nonProof) == false); // dev: getNonExistProofForKey not available - Proof.verify(nonProof, spec, commitmentRoot, key); + //require(NonExistenceProof.isNil(nonProof) == false); // dev: getNonExistProofForKey not available + if (NonExistenceProof.isNil(nonProof)) return VerifyNonMembershipError.NonExistenceProofIsNil; + Proof.VerifyNonExistenceError vCode = Proof.verify(nonProof, spec, commitmentRoot, key); + if (vCode != Proof.VerifyNonExistenceError.None) return VerifyNonMembershipError.ProofVerify; + + return VerifyNonMembershipError.None; } /* -- temporarily disabled as they are not covered by unit tests struct BatchItem { @@ -90,10 +108,12 @@ library Ics23 { contract ICS23_UnitTest { function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) public pure { - Ics23.verifyMembership(spec, commitmentRoot, proof, key, value); + Ics23.VerifyMembershipError vCode = Ics23.verifyMembership(spec, commitmentRoot, proof, key, value); + require(vCode == Ics23.VerifyMembershipError.None); } function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) public pure { - Ics23.verifyNonMembership(spec, commitmentRoot, proof, key); + Ics23.VerifyNonMembershipError vCode = Ics23.verifyNonMembership(spec, commitmentRoot, proof, key); + require(vCode == Ics23.VerifyNonMembershipError.None); } /* -- temporarily disabled as they are not covered by unit tests function batchVerifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, Ics23.BatchItem[] memory items ) public pure { diff --git a/sol/contracts/ics23Ops.sol b/sol/contracts/ics23Ops.sol index 2b08e64f..27196e6d 100644 --- a/sol/contracts/ics23Ops.sol +++ b/sol/contracts/ics23Ops.sol @@ -8,76 +8,144 @@ import {Math} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/ma import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol"; library Ops { + bytes constant empty = new bytes(0); + enum ApplyLeafOpError { + None, + KeyLength, + ValueLength, + DoHash, + PrepareLeafData + } // LeafOp operations - function applyOp(LeafOp.Data memory leafOp, bytes memory key, bytes memory value) internal pure returns(bytes memory) { - require(key.length > 0); // dev: Leaf op needs key - require(value.length > 0); // dev: Leaf op needs value - bytes memory pKey = prepareLeafData(leafOp.prehash_key, leafOp.length, key); - bytes memory pValue = prepareLeafData(leafOp.prehash_value, leafOp.length, value); + function applyOp(LeafOp.Data memory leafOp, bytes memory key, bytes memory value) internal pure returns(bytes memory, ApplyLeafOpError) { + //require(key.length > 0); // dev: Leaf op needs key + if (key.length == 0) return (empty, ApplyLeafOpError.KeyLength); + //require(value.length > 0); // dev: Leaf op needs value + if (value.length == 0) return (empty, ApplyLeafOpError.ValueLength); + (bytes memory pKey, PrepareLeafDataError pCode1) = prepareLeafData(leafOp.prehash_key, leafOp.length, key); + if (pCode1 != PrepareLeafDataError.None) return (empty, ApplyLeafOpError.PrepareLeafData); + (bytes memory pValue, PrepareLeafDataError pCode2) = prepareLeafData(leafOp.prehash_value, leafOp.length, value); + if (pCode2 != PrepareLeafDataError.None) return (empty, ApplyLeafOpError.PrepareLeafData); bytes memory data = abi.encodePacked(leafOp.prefix, pKey, pValue); - return doHash(leafOp.hash, data); + (bytes memory hashed, DoHashError hCode) = doHash(leafOp.hash, data); + if (hCode != DoHashError.None) return (empty, ApplyLeafOpError.DoHash); + return(hashed, ApplyLeafOpError.None); + } + + enum PrepareLeafDataError { + None, + DoHash, + DoLengthOp + } + // preapare leaf data for encoding + function prepareLeafData(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) internal pure returns(bytes memory, PrepareLeafDataError) { + (bytes memory hased, DoHashError hCode) = doHashOrNoop(hashOp, data); + if (hCode != DoHashError.None)return (empty, PrepareLeafDataError.DoHash); + (bytes memory res, DoLengthOpError lCode) = doLengthOp(lenOp, hased); + if (lCode != DoLengthOpError.None) return (empty, PrepareLeafDataError.DoLengthOp); + + return (res, PrepareLeafDataError.None); } - function prepareLeafData(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) internal pure returns(bytes memory) { - bytes memory hdata = doHashOrNoop(hashOp, data); - return doLengthOp(lenOp, hdata); + + enum CheckAgainstSpecError{ + None, + Hash, + PreHashKey, + PreHashValue, + Length, + MinPrefixLength, + HasPrefix, + MaxPrefixLength } - function checkAgainstSpec(LeafOp.Data memory leafOp, ProofSpec.Data memory spec) internal pure { - require (leafOp.hash == spec.leaf_spec.hash); // dev: checkAgainstSpec for LeafOp - Unexpected HashOp - require(leafOp.prehash_key == spec.leaf_spec.prehash_key); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashKey - require(leafOp.prehash_value == spec.leaf_spec.prehash_value); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashValue"); - require(leafOp.length == spec.leaf_spec.length); // dev: checkAgainstSpec for LeafOp - Unexpected lengthOp + function checkAgainstSpec(LeafOp.Data memory leafOp, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { + //require (leafOp.hash == spec.leaf_spec.hash); // dev: checkAgainstSpec for LeafOp - Unexpected HashOp + if (leafOp.hash != spec.leaf_spec.hash) return CheckAgainstSpecError.Hash; + //require(leafOp.prehash_key == spec.leaf_spec.prehash_key); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashKey + if (leafOp.prehash_key != spec.leaf_spec.prehash_key) return CheckAgainstSpecError.PreHashKey; + //require(leafOp.prehash_value == spec.leaf_spec.prehash_value); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashValue"); + if (leafOp.prehash_value != spec.leaf_spec.prehash_value) return CheckAgainstSpecError.PreHashValue; + //require(leafOp.length == spec.leaf_spec.length); // dev: checkAgainstSpec for LeafOp - Unexpected lengthOp + if (leafOp.length != spec.leaf_spec.length) return CheckAgainstSpecError.Length; bool hasprefix = hasPrefix(leafOp.prefix, spec.leaf_spec.prefix); - require(hasprefix); // dev: checkAgainstSpec for LeafOp - Leaf Prefix doesn't start with + //require(hasprefix); // dev: checkAgainstSpec for LeafOp - Leaf Prefix doesn't start with + if (hasprefix == false) return CheckAgainstSpecError.HasPrefix; + + return CheckAgainstSpecError.None; } + enum ApplyInnerOpError { + None, + ChildLength, + DoHash + } // InnerOp operations - function applyOp(InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory) { - require(child.length > 0); // dev: Inner op needs child value + function applyOp(InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory, ApplyInnerOpError) { + //require(child.length > 0); // dev: Inner op needs child value + if (child.length == 0) return (empty, ApplyInnerOpError.ChildLength); bytes memory preImage = abi.encodePacked(innerOp.prefix, child, innerOp.suffix); - return doHash(innerOp.hash, preImage); + (bytes memory hashed, DoHashError code) = doHash(innerOp.hash, preImage); + if (code != DoHashError.None) return (empty, ApplyInnerOpError.DoHash); + + return (hashed, ApplyInnerOpError.None); } - function checkAgainstSpec(InnerOp.Data memory innerOp, ProofSpec.Data memory spec) internal pure { - require(innerOp.hash == spec.inner_spec.hash); // dev: checkAgainstSpec for InnerOp - Unexpected HashOp + + function checkAgainstSpec(InnerOp.Data memory innerOp, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { + //require(innerOp.hash == spec.inner_spec.hash); // dev: checkAgainstSpec for InnerOp - Unexpected HashOp + if (innerOp.hash != spec.inner_spec.hash) return CheckAgainstSpecError.Hash; uint256 minPrefixLength = SafeCast.toUint256(spec.inner_spec.min_prefix_length); - require(innerOp.prefix.length >= minPrefixLength); // dev: InnerOp prefix too short; + //require(innerOp.prefix.length >= minPrefixLength); // dev: InnerOp prefix too short; + if (innerOp.prefix.length < minPrefixLength) return CheckAgainstSpecError.MinPrefixLength; bytes memory leafPrefix = spec.leaf_spec.prefix; bool hasprefix = hasPrefix(innerOp.prefix, leafPrefix); - require(hasprefix == false); // dev: Inner Prefix starts with wrong value + //require(hasprefix == false); // dev: Inner Prefix starts with wrong value + if (hasprefix) return CheckAgainstSpecError.HasPrefix; uint256 childSize = SafeCast.toUint256(spec.inner_spec.child_size); uint256 maxLeftChildBytes = (spec.inner_spec.child_order.length - 1) * childSize; uint256 maxPrefixLength = SafeCast.toUint256(spec.inner_spec.max_prefix_length); - require(innerOp.prefix.length <= maxPrefixLength + maxLeftChildBytes); // dev: InnerOp prefix too long + //require(innerOp.prefix.length <= maxPrefixLength + maxLeftChildBytes); // dev: InnerOp prefix too long + if (innerOp.prefix.length > maxPrefixLength + maxLeftChildBytes) return CheckAgainstSpecError.MaxPrefixLength; + + return CheckAgainstSpecError.None; } - function doHashOrNoop(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory) { + function doHashOrNoop(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory, DoHashError) { if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.NO_HASH) { - return preImage; + return (preImage, DoHashError.None); } return doHash(hashOp, preImage); } - function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory) { + enum DoHashError { + None, + Sha512, + Sha512_256, + Unsupported + } + function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory, DoHashError) { if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA256) { - return abi.encodePacked(sha256(preImage)); + return (abi.encodePacked(sha256(preImage)), DoHashError.None); } if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.KECCAK) { - return abi.encodePacked(keccak256(preImage)); + return (abi.encodePacked(keccak256(preImage)), DoHashError.None); } if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.RIPEMD160) { - return abi.encodePacked(ripemd160(preImage)); + return (abi.encodePacked(ripemd160(preImage)), DoHashError.None); } if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.BITCOIN) { bytes memory tmp = abi.encodePacked(sha256(preImage)); - return abi.encodePacked(ripemd160(tmp)); + return (abi.encodePacked(ripemd160(tmp)), DoHashError.None); } + //require(hashOp != PROOFS_PROTO_GLOBAL_ENUMS.HashOp.Sha512); // dev: SHA512 not supported if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA512) { - revert(); // dev: SHA512 not supported + return (empty, DoHashError.Sha512); } + //require(hashOp != PROOFS_PROTO_GLOBAL_ENUMS.HashOp.Sha512_256); // dev: SHA512_256 not supported if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA512_256) { - revert(); // dev: SHA512_256 not supported + return (empty, DoHashError.Sha512_256); } - revert(); // dev: Unsupported hashOp + //revert(); // dev: Unsupported hashOp + return (empty, DoHashError.Unsupported); } function compare(bytes memory a, bytes memory b) internal pure returns(int) { @@ -99,23 +167,33 @@ library Ops { } // private - function doLengthOp(PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) private pure returns(bytes memory) { + enum DoLengthOpError { + None, + Require32DataLength, + Require64DataLength, + Unsupported + } + function doLengthOp(PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) private pure returns(bytes memory, DoLengthOpError) { if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.NO_PREFIX) { - return data; + return (data, DoLengthOpError.None); } if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.VAR_PROTO) { uint256 sz = ProtoBufRuntime._sz_varint(data.length); bytes memory encoded = new bytes(sz); ProtoBufRuntime._encode_varint(data.length, 32, encoded); - return abi.encodePacked(encoded, data); + return (abi.encodePacked(encoded, data), DoLengthOpError.None); } if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.REQUIRE_32_BYTES) { - require(data.length == 32); // dev: data.length != 32 - return data; + //require(data.length == 32); // dev: data.length != 32 + if (data.length != 32) return (empty, DoLengthOpError.Require32DataLength); + + return (data, DoLengthOpError.None); } if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.REQUIRE_64_BYTES) { - require(data.length == 64); // dev: data.length != 64" - return data; + //require(data.length == 64); // dev: data.length != 64" + if (data.length != 64) return (empty, DoLengthOpError.Require64DataLength); + + return (data, DoLengthOpError.None); } if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.FIXED32_LITTLE) { uint32 size = SafeCast.toUint32(data.length); @@ -127,9 +205,10 @@ library Ops { littleE[1] = sizeB[2]; littleE[2] = sizeB[1]; littleE[3] = sizeB[0]; - return abi.encodePacked(littleE, data); + return (abi.encodePacked(littleE, data), DoLengthOpError.None); } - revert(); // dev: Unsupported lenOp + //revert(); // dev: Unsupported lenOp + return (empty, DoLengthOpError.Unsupported); } function hasPrefix(bytes memory element, bytes memory prefix) private pure returns (bool) { @@ -149,18 +228,26 @@ library Ops { contract Ops_UnitTest { function applyLeafOp(LeafOp.Data memory leaf, bytes memory key, bytes memory value) public pure returns(bytes memory) { - return Ops.applyOp(leaf, key, value); + (bytes memory res, Ops.ApplyLeafOpError aCode) = Ops.applyOp(leaf, key, value); + require(aCode == Ops.ApplyLeafOpError.None); // dev: expand this require to check error code + return res; } - function checkAgainstLeafOpSpec(LeafOp.Data memory op, ProofSpec.Data memory spec) public pure { - return Ops.checkAgainstSpec(op, spec); + function checkAgainstLeafOpSpec(LeafOp.Data memory op, ProofSpec.Data memory spec) public pure { + Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); + require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code } function applyInnerOp(InnerOp.Data memory inner,bytes memory child) public pure returns(bytes memory) { - return Ops.applyOp(inner, child); + (bytes memory res, Ops.ApplyInnerOpError aCode) = Ops.applyOp(inner, child); + require(aCode == Ops.ApplyInnerOpError.None); // dev: expand this require to check error code + return res; } function checkAgainstInnerOpSpec(InnerOp.Data memory op, ProofSpec.Data memory spec) public pure { - return Ops.checkAgainstSpec(op, spec); + Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); + require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code } function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) public pure returns(bytes memory) { - return Ops.doHash(hashOp, preImage); + (bytes memory res, Ops.DoHashError hCode) = Ops.doHash(hashOp, preImage); + require(hCode == Ops.DoHashError.None); // dev: expand this require to check error code + return res; } } diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol index 82c849a4..f5fae402 100644 --- a/sol/contracts/ics23Proof.sol +++ b/sol/contracts/ics23Proof.sol @@ -9,84 +9,155 @@ import {Compress} from "./ics23Compress.sol"; import {Ops} from "./ics23Ops.sol"; library Proof{ + bytes constant empty = new bytes(0); + + enum VerifyExistenceError{ + None, + KeyNotMatching, + ValueNotMatching, + CheckSpec, + CalculateRoot, + RootNotMatching + } // ExistenceProof - function verify(ExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key, bytes memory value) internal pure { - require(BytesLib.equal(proof.key, key)); // dev: Provided key doesn't match proof - require(BytesLib.equal(proof.value, value)); // dev: Provided value doesn't match proof - checkAgainstSpec(proof, spec); - bytes memory root = calculateRoot(proof); - require(BytesLib.equal(root, commitmentRoot)); // dev: Calculcated root doesn't match provided root + function verify(ExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key, bytes memory value) internal pure returns(VerifyExistenceError) { + //require(BytesLib.equal(proof.key, key)); // dev: Provided key doesn't match proof + bool keyMatch = BytesLib.equal(proof.key, key); + if (keyMatch == false) return VerifyExistenceError.KeyNotMatching; + //require(BytesLib.equal(proof.value, value)); // dev: Provided value doesn't match proof + bool valueMatch = BytesLib.equal(proof.value, value); + if (valueMatch == false) return VerifyExistenceError.ValueNotMatching; + CheckAgainstSpecError cCode = checkAgainstSpec(proof, spec); + if (cCode != CheckAgainstSpecError.None) return VerifyExistenceError.CheckSpec; + (bytes memory root, CalculateRootError rCode) = calculateRoot(proof); + if (rCode != CalculateRootError.None) return VerifyExistenceError.CalculateRoot; + //require(BytesLib.equal(root, commitmentRoot)); // dev: Calculcated root doesn't match provided root + bool rootMatch = BytesLib.equal(root, commitmentRoot); + if (rootMatch == false) return VerifyExistenceError.RootNotMatching; + + return VerifyExistenceError.None; } - function calculateRoot(ExistenceProof.Data memory proof) internal pure returns(bytes memory) { - require(LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp - bytes memory root = Ops.applyOp(proof.leaf, proof.key, proof.value); + enum CalculateRootError { + None, + LeafNil, + LeafOp, + PathOp, + BatchEntriesLength, + BatchEntryEmpty, + EmptyProof + } + function calculateRoot(ExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { + //require(LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp + if (LeafOp.isNil(proof.leaf)) return (empty, CalculateRootError.LeafNil); + (bytes memory root, Ops.ApplyLeafOpError lCode) = Ops.applyOp(proof.leaf, proof.key, proof.value); + if (lCode != Ops.ApplyLeafOpError.None) return (empty, CalculateRootError.LeafOp); for (uint i = 0; i < proof.path.length; i++) { - root = Ops.applyOp(proof.path[i], root); + Ops.ApplyInnerOpError iCode; + (root, iCode) = Ops.applyOp(proof.path[i], root); + if (iCode != Ops.ApplyInnerOpError.None) return (empty, CalculateRootError.PathOp); } - return root; + + return (root, CalculateRootError.None); } - function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) internal pure { + enum CheckAgainstSpecError{ + None, + EmptyLeaf, + OpsCheckAgainstSpec, + InnerOpsDepthTooShort, + InnerOpsDepthTooLong + } + function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { // LeafOp.isNil does not work - require(LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp - Ops.checkAgainstSpec(proof.leaf, spec); + //require(LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp + if (LeafOp._empty(proof.leaf)) return CheckAgainstSpecError.EmptyLeaf; + Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(proof.leaf, spec); + if (cCode != Ops.CheckAgainstSpecError.None) return CheckAgainstSpecError.OpsCheckAgainstSpec; if (spec.min_depth > 0) { - bool innerOpsDepthTooShort = proof.path.length >= SafeCast.toUint256(int256(spec.min_depth)); - require(innerOpsDepthTooShort); // dev: InnerOps depth too short + bool innerOpsDepthTooShort = proof.path.length < SafeCast.toUint256(int256(spec.min_depth)); + //require(innerOpsDepthTooShort == false); // dev: InnerOps depth too short + if (innerOpsDepthTooShort) return CheckAgainstSpecError.InnerOpsDepthTooShort; } if (spec.max_depth > 0) { - bool innerOpsDepthTooLong = proof.path.length <= SafeCast.toUint256(int256(spec.max_depth)); - require(innerOpsDepthTooLong); // dev: InnerOps depth too long + bool innerOpsDepthTooLong = proof.path.length > SafeCast.toUint256(int256(spec.max_depth)); + //require(innerOpsDepthTooLong == false); // dev: InnerOps depth too long + if (innerOpsDepthTooLong) return CheckAgainstSpecError.InnerOpsDepthTooLong; } for(uint i = 0; i < proof.path.length; i++) { - Ops.checkAgainstSpec(proof.path[i], spec); + Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(proof.path[i], spec); + if (cCode != Ops.CheckAgainstSpecError.None) return CheckAgainstSpecError.OpsCheckAgainstSpec; } } + enum VerifyNonExistenceError { + None, + VerifyLeft, + VerifyRight, + LeftAndRightKeyEmpty, + RightKeyRange, + LeftKeyRange, + RightProofLeftMost, + LeftProofRightMost, + IsLeftNeighbor + } // NonExistenceProof - function verify(NonExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key) internal pure { + function verify(NonExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key) internal pure returns(VerifyNonExistenceError) { bytes memory leftKey; bytes memory rightKey; // ExistenceProof.isNil does not work if (ExistenceProof._empty(proof.left) == false) { - verify(proof.left, spec, commitmentRoot, proof.left.key, proof.left.value); + VerifyExistenceError eCode = verify(proof.left, spec, commitmentRoot, proof.left.key, proof.left.value); + if (eCode != VerifyExistenceError.None) return VerifyNonExistenceError.VerifyLeft; + leftKey = proof.left.key; } if (ExistenceProof._empty(proof.right) == false) { - verify(proof.right, spec, commitmentRoot, proof.right.key, proof.right.value); + VerifyExistenceError eCode = verify(proof.right, spec, commitmentRoot, proof.right.key, proof.right.value); + if (eCode != VerifyExistenceError.None) return VerifyNonExistenceError.VerifyRight; + rightKey = proof.right.key; } // If both proofs are missing, this is not a valid proof - require(leftKey.length > 0 || rightKey.length > 0); // dev: both left and right proofs missing + //require(leftKey.length > 0 || rightKey.length > 0); // dev: both left and right proofs missing + if (leftKey.length == 0 && rightKey.length == 0) return VerifyNonExistenceError.LeftAndRightKeyEmpty; // Ensure in valid range - if (rightKey.length > 0) { - require(Ops.compare(key, rightKey) < 0); // dev: key is not left of right proof + if (rightKey.length > 0 && Ops.compare(key, rightKey) >= 0) { + //require(Ops.compare(key, rightKey) < 0); // dev: key is not left of right proof + return VerifyNonExistenceError.RightKeyRange; } - if (leftKey.length > 0) { - require(Ops.compare(key, leftKey) > 0); // dev: key is not right of left proof + if (leftKey.length > 0 && Ops.compare(key, leftKey) <= 0) { + //require(Ops.compare(key, leftKey) > 0); // dev: key is not right of left proof + return VerifyNonExistenceError.LeftKeyRange; } if (leftKey.length == 0) { - require(isLeftMost(spec.inner_spec, proof.right.path)); // dev: left proof missing, right proof must be left-most + //require(isLeftMost(spec.inner_spec, proof.right.path)); // dev: left proof missing, right proof must be left-most + if(isLeftMost(spec.inner_spec, proof.right.path) == false) return VerifyNonExistenceError.RightProofLeftMost; } else if (rightKey.length == 0) { - require(isRightMost(spec.inner_spec, proof.left.path)); // dev: isRightMost: right proof missing, left proof must be right-most + //require(isRightMost(spec.inner_spec, proof.left.path)); // dev: isRightMost: right proof missing, left proof must be right-most + if (isRightMost(spec.inner_spec, proof.left.path) == false) return VerifyNonExistenceError.LeftProofRightMost; } else { - require(isLeftNeighbor(spec.inner_spec, proof.left.path, proof.right.path)); // dev: isLeftNeighbor: right proof missing, left proof must be right-most + //require(isLeftNeighbor(spec.inner_spec, proof.left.path, proof.right.path)); // dev: isLeftNeighbor: right proof missing, left proof must be right-most + bool isLeftNeigh = isLeftNeighbor(spec.inner_spec, proof.left.path, proof.right.path); + if (isLeftNeigh == false) return VerifyNonExistenceError.IsLeftNeighbor; } + + return VerifyNonExistenceError.None; } - function calculateRoot(NonExistenceProof.Data memory proof) internal pure returns(bytes memory ) { + function calculateRoot(NonExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { if (ExistenceProof._empty(proof.left) == false) { return calculateRoot(proof.left); } if (ExistenceProof._empty(proof.right) == false) { return calculateRoot(proof.right); } - revert(); // dev: Nonexistence proof has empty Left and Right proof + //revert(); // dev: Nonexistence proof has empty Left and Right proof + return (empty, CalculateRootError.EmptyProof); } // commitment proof - function calculateRoot(CommitmentProof.Data memory proof) internal pure returns(bytes memory) { + function calculateRoot(CommitmentProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { if (ExistenceProof._empty(proof.exist) == false) { return calculateRoot(proof.exist); } @@ -94,8 +165,10 @@ library Proof{ return calculateRoot(proof.nonexist); } if (BatchProof._empty(proof.batch) == false) { - require(proof.batch.entries.length > 0); // dev: batch proof has no entry - require(BatchEntry._empty(proof.batch.entries[0]) == false); // dev: batch proof has empty entry + //require(proof.batch.entries.length > 0); // dev: batch proof has no entry + if (proof.batch.entries.length == 0) return (empty, CalculateRootError.BatchEntriesLength); + //require(BatchEntry._empty(proof.batch.entries[0]) == false); // dev: batch proof has empty entry + if (BatchEntry._empty(proof.batch.entries[0])) return (empty, CalculateRootError.BatchEntryEmpty); if (ExistenceProof._empty(proof.batch.entries[0].exist) == false) { return calculateRoot(proof.batch.entries[0].exist); } @@ -106,13 +179,15 @@ library Proof{ if (CompressedBatchProof._empty(proof.compressed) == false) { return calculateRoot(Compress.decompress(proof)); } - revert(); // dev: calculateRoot(CommitmentProof) empty proof + //revert(); // dev: calculateRoot(CommitmentProof) empty proof + return (empty, CalculateRootError.EmptyProof); } // private function isLeftMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool) { - (uint minPrefix, uint maxPrefix, uint suffix) = getPadding(spec, 0); + (uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError gCode) = getPadding(spec, 0); + if (gCode != GetPaddingError.None) return false; for (uint i = 0; i < path.length; i++) { if (hasPadding(path[i], minPrefix, maxPrefix, suffix) == false){ return false; @@ -123,15 +198,27 @@ library Proof{ function isRightMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool){ uint last = spec.child_order.length - 1; - (uint minPrefix, uint maxPrefix, uint suffix) = getPadding(spec, last); + (uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError gCode) = getPadding(spec, last); + if (gCode != GetPaddingError.None) return false; for (uint i = 0; i < path.length; i++) { if (hasPadding(path[i], minPrefix, maxPrefix, suffix) == false){ return false; } } + return true; } + function isLeftStep(InnerSpec.Data memory spec, InnerOp.Data memory left, InnerOp.Data memory right) private pure returns(bool){ + (uint leftIdx, OrderFromPaddingError lCode) = orderFromPadding(spec, left); + if (lCode != OrderFromPaddingError.None) return false; + (uint rightIdx, OrderFromPaddingError rCode) = orderFromPadding(spec, right); + if (lCode != OrderFromPaddingError.None) return false; + if (rCode != OrderFromPaddingError.None) return false; + + return rightIdx == leftIdx + 1; + } + function isLeftNeighbor(InnerSpec.Data memory spec, InnerOp.Data[] memory left, InnerOp.Data[] memory right) private pure returns(bool) { uint leftIdx = left.length - 1; uint rightIdx = right.length - 1; @@ -157,40 +244,51 @@ library Proof{ return true; } - function isLeftStep(InnerSpec.Data memory spec, InnerOp.Data memory left, InnerOp.Data memory right) private pure returns(bool){ - uint leftIdx = orderFromPadding(spec, left); - uint rightIdx = orderFromPadding(spec, right); - return rightIdx == leftIdx + 1; + enum OrderFromPaddingError { + None, + NotFound, + GetPadding } - - function orderFromPadding(InnerSpec.Data memory spec, InnerOp.Data memory op) private pure returns(uint) { + function orderFromPadding(InnerSpec.Data memory spec, InnerOp.Data memory op) private pure returns(uint, OrderFromPaddingError) { uint256 maxBranch = spec.child_order.length; for(uint branch = 0; branch < maxBranch; branch++) { - (uint minp, uint maxp, uint suffix) = getPadding(spec, branch); - if (hasPadding(op, minp, maxp, suffix) == true) { - return branch; - } + (uint minp, uint maxp, uint suffix, GetPaddingError gCode) = getPadding(spec, branch); + if (gCode != GetPaddingError.None) return (0, OrderFromPaddingError.GetPadding); + if (hasPadding(op, minp, maxp, suffix) == true) return (branch, OrderFromPaddingError.None); } - revert(); // dev: Cannot find any valid spacing for this node + //revert(); // dev: Cannot find any valid spacing for this node + return (0, OrderFromPaddingError.NotFound); } - function getPadding(InnerSpec.Data memory spec, uint branch) private pure returns(uint minPrefix, uint maxPrefix, uint suffix) { + enum GetPaddingError { + None, + GetPosition + } + function getPadding(InnerSpec.Data memory spec, uint branch) private pure returns(uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError) { uint uChildSize = SafeCast.toUint256(spec.child_size); - uint idx = getPosition(spec.child_order, branch); + (uint idx, GetPositionError gCode) = getPosition(spec.child_order, branch); + if (gCode != GetPositionError.None) return (0, 0, 0, GetPaddingError.GetPosition); uint prefix = idx * uChildSize; minPrefix = prefix + SafeCast.toUint256(spec.min_prefix_length); maxPrefix = prefix + SafeCast.toUint256(spec.max_prefix_length); suffix = (spec.child_order.length - 1 - idx) * uChildSize; + + return (minPrefix, maxPrefix, suffix, GetPaddingError.None); } - function getPosition(int32[] memory order, uint branch) private pure returns(uint) { - require(branch < order.length); // dev: invalid branch + enum GetPositionError { + None, + BranchLength, + NoFound + } + function getPosition(int32[] memory order, uint branch) private pure returns(uint, GetPositionError) { + //require(branch < order.length); // dev: invalid branch + if (branch >= order.length) return (0, GetPositionError.BranchLength); for (uint i = 0; i < order.length; i++) { - if (SafeCast.toUint256(order[i]) == branch) { - return i; - } + if (SafeCast.toUint256(order[i]) == branch) return (i, GetPositionError.None); } - revert(); // dev: branch not found in order + //revert(); // dev: branch not found in order + return (0, GetPositionError.NoFound); } function hasPadding(InnerOp.Data memory op, uint minPrefix, uint maxPrefix, uint suffix) private pure returns(bool) { @@ -213,13 +311,18 @@ library Proof{ contract Proof_UnitTest { function calculateExistenceProofRoot(ExistenceProof.Data memory proof) public pure returns(bytes memory) { - return Proof.calculateRoot(proof); + (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); + require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code + return res; } function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) public pure { - return Proof.checkAgainstSpec(proof, spec); + Proof.CheckAgainstSpecError cCode = Proof.checkAgainstSpec(proof, spec); + require(cCode == Proof.CheckAgainstSpecError.None); // dev: expand this require to check error code } function calculateCommitmentProofRoot(CommitmentProof.Data memory proof) public pure returns(bytes memory) { - return Proof.calculateRoot(proof); + (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); + require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code + return res; } function protobufDecodeCommitmentProof(bytes memory msg) public pure returns(CommitmentProof.Data memory) { CommitmentProof.Data memory res = CommitmentProof.decode(msg); diff --git a/sol/contracts/proofs.sol b/sol/contracts/proofs.sol index 780024f7..1ab141c5 100644 --- a/sol/contracts/proofs.sol +++ b/sol/contracts/proofs.sol @@ -6,5496 +6,5496 @@ import "./GoogleProtobufAny.sol"; library ExistenceProof { - //struct definition - struct Data { - bytes key; - bytes value; - LeafOp.Data leaf; - InnerOp.Data[] path; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + bytes key; + bytes value; + LeafOp.Data leaf; + InnerOp.Data[] path; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[5] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - pointer = offset; - r.path = new InnerOp.Data[](counters[4]); - - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, nil(), counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, nil(), counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_key( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_value( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.value = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_leaf( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.leaf = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_path( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.path[r.path.length - counters[4]] = x; - if (counters[4] > 0) counters[4] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_LeafOp(uint256 p, bytes memory bs) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.path = new InnerOp.Data[](counters[4]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, nil(), counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, nil(), counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.value = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_leaf( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.leaf = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_path( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.path[r.path.length - counters[4]] = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_LeafOp(uint256 p, bytes memory bs) internal pure returns (LeafOp.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_InnerOp(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_InnerOp(uint256 p, bytes memory bs) internal pure returns (InnerOp.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - uint256 i; - if (r.key.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); - } - if (r.value.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); - } - - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += LeafOp._encode_nested(r.leaf, pointer, bs); - - if (r.path.length != 0) { - for(i = 0; i < r.path.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs) - ; - pointer += InnerOp._encode_nested(r.path[i], pointer, bs); - } - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + if (r.value.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += LeafOp._encode_nested(r.leaf, pointer, bs); + + if (r.path.length != 0) { + for(i = 0; i < r.path.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += InnerOp._encode_nested(r.path[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e;uint256 i; - e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); - e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); - e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); - for(i = 0; i < r.path.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.path[i])); - } - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.key.length != 0) { - return false; - } - - if (r.value.length != 0) { - return false; - } - - if (r.path.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.key = input.key; - output.value = input.value; - LeafOp.store(input.leaf, output.leaf); - - for(uint256 i4 = 0; i4 < input.path.length; i4++) { - output.path.push(input.path[i4]); - } - - - } - - - //array helpers for Path - /** - * @dev Add value to an array - * @param self The in-memory struct - * @param value The value to add - */ - function addPath(Data memory self, InnerOp.Data memory value) internal pure { - /** - * First resize the array. Then add the new element to the end. - */ - InnerOp.Data[] memory tmp = new InnerOp.Data[](self.path.length + 1); - for (uint256 i = 0; i < self.path.length; i++) { - tmp[i] = self.path[i]; - } - tmp[self.path.length] = value; - self.path = tmp; - } - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); + for(i = 0; i < r.path.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.path[i])); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + if (r.value.length != 0) { + return false; + } + + if (r.path.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + output.value = input.value; + LeafOp.store(input.leaf, output.leaf); + + for(uint256 i4 = 0; i4 < input.path.length; i4++) { + output.path.push(input.path[i4]); + } + + + } + + + //array helpers for Path + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addPath(Data memory self, InnerOp.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + InnerOp.Data[] memory tmp = new InnerOp.Data[](self.path.length + 1); + for (uint256 i = 0; i < self.path.length; i++) { + tmp[i] = self.path[i]; + } + tmp[self.path.length] = value; + self.path = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library ExistenceProof library NonExistenceProof { - //struct definition - struct Data { - bytes key; - ExistenceProof.Data left; - ExistenceProof.Data right; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + bytes key; + ExistenceProof.Data left; + ExistenceProof.Data right; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[4] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_left(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_right(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_key( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_left( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.left = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_right( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.right = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_ExistenceProof(uint256 p, bytes memory bs) + { + Data memory r; + uint[4] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_left(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_right(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_left( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.left = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_right( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.right = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ExistenceProof(uint256 p, bytes memory bs) internal pure returns (ExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - if (r.key.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); - } - - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ExistenceProof._encode_nested(r.left, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ExistenceProof._encode_nested(r.right, pointer, bs); - - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.left, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.right, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.left)); - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.right)); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.key.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.key = input.key; - ExistenceProof.store(input.left, output.left); - ExistenceProof.store(input.right, output.right); - - } - - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.right)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + ExistenceProof.store(input.left, output.left); + ExistenceProof.store(input.right, output.right); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library NonExistenceProof library CommitmentProof { - //struct definition - struct Data { - ExistenceProof.Data exist; - NonExistenceProof.Data nonexist; - BatchProof.Data batch; - CompressedBatchProof.Data compressed; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + ExistenceProof.Data exist; + NonExistenceProof.Data nonexist; + BatchProof.Data batch; + CompressedBatchProof.Data compressed; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[5] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_exist(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_nonexist(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_batch(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_compressed(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_exist( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.exist = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_nonexist( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.nonexist = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_batch( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (BatchProof.Data memory x, uint256 sz) = _decode_BatchProof(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.batch = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_compressed( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedBatchProof.Data memory x, uint256 sz) = _decode_CompressedBatchProof(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.compressed = x; - if (counters[4] > 0) counters[4] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_ExistenceProof(uint256 p, bytes memory bs) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_exist(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_batch(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_compressed(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.exist = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_nonexist( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.nonexist = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_batch( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (BatchProof.Data memory x, uint256 sz) = _decode_BatchProof(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.batch = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_compressed( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedBatchProof.Data memory x, uint256 sz) = _decode_CompressedBatchProof(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.compressed = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ExistenceProof(uint256 p, bytes memory bs) internal pure returns (ExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_NonExistenceProof(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_NonExistenceProof(uint256 p, bytes memory bs) internal pure returns (NonExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_BatchProof(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_BatchProof(uint256 p, bytes memory bs) internal pure returns (BatchProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (BatchProof.Data memory r, ) = BatchProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_CompressedBatchProof(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (BatchProof.Data memory r, ) = BatchProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedBatchProof(uint256 p, bytes memory bs) internal pure returns (CompressedBatchProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (CompressedBatchProof.Data memory r, ) = CompressedBatchProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedBatchProof.Data memory r, ) = CompressedBatchProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += BatchProof._encode_nested(r.batch, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += CompressedBatchProof._encode_nested(r.compressed, pointer, bs); - - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += BatchProof._encode_nested(r.batch, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedBatchProof._encode_nested(r.compressed, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); - e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); - e += 1 + ProtoBufRuntime._sz_lendelim(BatchProof._estimate(r.batch)); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchProof._estimate(r.compressed)); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); + e += 1 + ProtoBufRuntime._sz_lendelim(BatchProof._estimate(r.batch)); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchProof._estimate(r.compressed)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + ExistenceProof.store(input.exist, output.exist); + NonExistenceProof.store(input.nonexist, output.nonexist); + BatchProof.store(input.batch, output.batch); + CompressedBatchProof.store(input.compressed, output.compressed); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CommitmentProof - return true; - } +library LeafOp { - //store function + //struct definition + struct Data { + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; + PROOFS_PROTO_GLOBAL_ENUMS.HashOp prehash_key; + PROOFS_PROTO_GLOBAL_ENUMS.HashOp prehash_value; + PROOFS_PROTO_GLOBAL_ENUMS.LengthOp length; + bytes prefix; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) + internal + pure + returns (Data memory, uint) + { + Data memory r; + uint[6] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_hash(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_prehash_key(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_prehash_value(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_length(pointer, bs, r, counters); + } + else if (fieldId == 5) { + pointer += _read_prefix(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[1] += 1; + } else { + r.hash = x; + if(counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prehash_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[2] += 1; + } else { + r.prehash_key = x; + if(counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prehash_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[3] += 1; + } else { + r.prehash_value = x; + if(counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_length( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.LengthOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_LengthOp(tmp); + if (isNil(r)) { + counters[4] += 1; + } else { + r.length = x; + if(counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prefix( + uint256 p, + bytes memory bs, + Data memory r, + uint[6] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.prefix = x; + if (counters[5] > 0) counters[5] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { + uint256 offset = p; + uint256 pointer = p; + + if (uint(r.hash) != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); + pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); + } + if (uint(r.prehash_key) != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_prehash_key = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_key); + pointer += ProtoBufRuntime._encode_enum(_enum_prehash_key, pointer, bs); + } + if (uint(r.prehash_value) != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_prehash_value = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_value); + pointer += ProtoBufRuntime._encode_enum(_enum_prehash_value, pointer, bs); + } + if (uint(r.length) != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_length = PROOFS_PROTO_GLOBAL_ENUMS.encode_LengthOp(r.length); + pointer += ProtoBufRuntime._encode_enum(_enum_length, pointer, bs); + } + if (r.prefix.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 5, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.prefix, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) + internal + pure + returns (uint) + { /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - ExistenceProof.store(input.exist, output.exist); - NonExistenceProof.store(input.nonexist, output.nonexist); - BatchProof.store(input.batch, output.batch); - CompressedBatchProof.store(input.compressed, output.compressed); + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_key)); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_value)); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_LengthOp(r.length)); + e += 1 + ProtoBufRuntime._sz_lendelim(r.prefix.length); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (uint(r.hash) != 0) { + return false; + } + + if (uint(r.prehash_key) != 0) { + return false; + } + + if (uint(r.prehash_value) != 0) { + return false; + } + + if (uint(r.length) != 0) { + return false; + } + + if (r.prefix.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.hash = input.hash; + output.prehash_key = input.prehash_key; + output.prehash_value = input.prehash_value; + output.length = input.length; + output.prefix = input.prefix; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library LeafOp - } +library InnerOp { - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } -} -//library CommitmentProof - -library LeafOp { - - - //struct definition - struct Data { - PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; - PROOFS_PROTO_GLOBAL_ENUMS.HashOp prehash_key; - PROOFS_PROTO_GLOBAL_ENUMS.HashOp prehash_value; - PROOFS_PROTO_GLOBAL_ENUMS.LengthOp length; - bytes prefix; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; + bytes prefix; + bytes suffix; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[6] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_hash(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_prehash_key(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_prehash_value(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_length(pointer, bs, r, counters); - } - else if (fieldId == 5) { - pointer += _read_prefix(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_hash( - uint256 p, - bytes memory bs, - Data memory r, - uint[6] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); - PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[1] += 1; - } else { - r.hash = x; - if(counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_prehash_key( - uint256 p, - bytes memory bs, - Data memory r, - uint[6] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); - PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[2] += 1; - } else { - r.prehash_key = x; - if(counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_prehash_value( - uint256 p, - bytes memory bs, - Data memory r, - uint[6] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); - PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[3] += 1; - } else { - r.prehash_value = x; - if(counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_length( - uint256 p, - bytes memory bs, - Data memory r, - uint[6] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); - PROOFS_PROTO_GLOBAL_ENUMS.LengthOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_LengthOp(tmp); - if (isNil(r)) { - counters[4] += 1; - } else { - r.length = x; - if(counters[4] > 0) counters[4] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_prefix( - uint256 p, - bytes memory bs, - Data memory r, - uint[6] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[5] += 1; - } else { - r.prefix = x; - if (counters[5] > 0) counters[5] -= 1; - } - return sz; - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) - internal - pure - returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - if (uint(r.hash) != 0) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); - pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); - } - if (uint(r.prehash_key) != 0) { - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - int32 _enum_prehash_key = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_key); - pointer += ProtoBufRuntime._encode_enum(_enum_prehash_key, pointer, bs); - } - if (uint(r.prehash_value) != 0) { - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - int32 _enum_prehash_value = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_value); - pointer += ProtoBufRuntime._encode_enum(_enum_prehash_value, pointer, bs); - } - if (uint(r.length) != 0) { - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - int32 _enum_length = PROOFS_PROTO_GLOBAL_ENUMS.encode_LengthOp(r.length); - pointer += ProtoBufRuntime._encode_enum(_enum_length, pointer, bs); - } - if (r.prefix.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 5, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.prefix, pointer, bs); - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) - internal - pure - returns (uint) - { - /** - * First encoded `r` into a temporary array, and encode the actual size used. - * Then copy the temporary array into `bs`. + { + Data memory r; + uint[4] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_hash(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_prefix(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_suffix(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); - e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_key)); - e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.prehash_value)); - e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_LengthOp(r.length)); - e += 1 + ProtoBufRuntime._sz_lendelim(r.prefix.length); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (uint(r.hash) != 0) { - return false; - } - - if (uint(r.prehash_key) != 0) { - return false; - } - - if (uint(r.prehash_value) != 0) { - return false; - } - - if (uint(r.length) != 0) { - return false; - } - - if (r.prefix.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.hash = input.hash; - output.prehash_key = input.prehash_key; - output.prehash_value = input.prehash_value; - output.length = input.length; - output.prefix = input.prefix; - - } - - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } -} -//library LeafOp - -library InnerOp { - - - //struct definition - struct Data { - PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; - bytes prefix; - bytes suffix; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) - internal - pure - returns (Data memory, uint) - { - Data memory r; - uint[4] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_hash(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_prefix(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_suffix(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_hash( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); - PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[1] += 1; - } else { - r.hash = x; - if(counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_prefix( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.prefix = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_suffix( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.suffix = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[1] += 1; + } else { + r.hash = x; + if(counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_prefix( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.prefix = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_suffix( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.suffix = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - if (uint(r.hash) != 0) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); - pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); - } - if (r.prefix.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.prefix, pointer, bs); - } - if (r.suffix.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.suffix, pointer, bs); - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + if (uint(r.hash) != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); + pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); + } + if (r.prefix.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.prefix, pointer, bs); + } + if (r.suffix.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.suffix, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); - e += 1 + ProtoBufRuntime._sz_lendelim(r.prefix.length); - e += 1 + ProtoBufRuntime._sz_lendelim(r.suffix.length); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (uint(r.hash) != 0) { - return false; - } - - if (r.prefix.length != 0) { - return false; - } - - if (r.suffix.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.hash = input.hash; - output.prefix = input.prefix; - output.suffix = input.suffix; - - } - - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); + e += 1 + ProtoBufRuntime._sz_lendelim(r.prefix.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.suffix.length); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (uint(r.hash) != 0) { + return false; + } + + if (r.prefix.length != 0) { + return false; + } + + if (r.suffix.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.hash = input.hash; + output.prefix = input.prefix; + output.suffix = input.suffix; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library InnerOp library ProofSpec { - //struct definition - struct Data { - LeafOp.Data leaf_spec; - InnerSpec.Data inner_spec; - int32 max_depth; - int32 min_depth; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + LeafOp.Data leaf_spec; + InnerSpec.Data inner_spec; + int32 max_depth; + int32 min_depth; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[5] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_leaf_spec(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_inner_spec(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_max_depth(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_min_depth(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_leaf_spec( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.leaf_spec = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_inner_spec( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (InnerSpec.Data memory x, uint256 sz) = _decode_InnerSpec(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.inner_spec = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_max_depth( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.max_depth = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_min_depth( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.min_depth = x; - if (counters[4] > 0) counters[4] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_LeafOp(uint256 p, bytes memory bs) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_leaf_spec(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_inner_spec(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_max_depth(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_min_depth(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_leaf_spec( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.leaf_spec = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_inner_spec( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (InnerSpec.Data memory x, uint256 sz) = _decode_InnerSpec(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.inner_spec = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_max_depth( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.max_depth = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_min_depth( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.min_depth = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_LeafOp(uint256 p, bytes memory bs) internal pure returns (LeafOp.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_InnerSpec(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_InnerSpec(uint256 p, bytes memory bs) internal pure returns (InnerSpec.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (InnerSpec.Data memory r, ) = InnerSpec._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (InnerSpec.Data memory r, ) = InnerSpec._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += LeafOp._encode_nested(r.leaf_spec, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += InnerSpec._encode_nested(r.inner_spec, pointer, bs); - - if (r.max_depth != 0) { - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_int32(r.max_depth, pointer, bs); - } - if (r.min_depth != 0) { - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_int32(r.min_depth, pointer, bs); - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += LeafOp._encode_nested(r.leaf_spec, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += InnerSpec._encode_nested(r.inner_spec, pointer, bs); + + if (r.max_depth != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.max_depth, pointer, bs); + } + if (r.min_depth != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.min_depth, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf_spec)); - e += 1 + ProtoBufRuntime._sz_lendelim(InnerSpec._estimate(r.inner_spec)); - e += 1 + ProtoBufRuntime._sz_int32(r.max_depth); - e += 1 + ProtoBufRuntime._sz_int32(r.min_depth); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.max_depth != 0) { - return false; - } - - if (r.min_depth != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - LeafOp.store(input.leaf_spec, output.leaf_spec); - InnerSpec.store(input.inner_spec, output.inner_spec); - output.max_depth = input.max_depth; - output.min_depth = input.min_depth; - - } - - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf_spec)); + e += 1 + ProtoBufRuntime._sz_lendelim(InnerSpec._estimate(r.inner_spec)); + e += 1 + ProtoBufRuntime._sz_int32(r.max_depth); + e += 1 + ProtoBufRuntime._sz_int32(r.min_depth); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.max_depth != 0) { + return false; + } + + if (r.min_depth != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + LeafOp.store(input.leaf_spec, output.leaf_spec); + InnerSpec.store(input.inner_spec, output.inner_spec); + output.max_depth = input.max_depth; + output.min_depth = input.min_depth; + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library ProofSpec library InnerSpec { - //struct definition - struct Data { - int32[] child_order; - int32 child_size; - int32 min_prefix_length; - int32 max_prefix_length; - bytes empty_child; - PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + int32[] child_order; + int32 child_size; + int32 min_prefix_length; + int32 max_prefix_length; + bytes empty_child; + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hash; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[7] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_child_order(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_child_size(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_min_prefix_length(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_max_prefix_length(pointer, bs, r, counters); - } - else if (fieldId == 5) { - pointer += _read_empty_child(pointer, bs, r, counters); - } - else if (fieldId == 6) { - pointer += _read_hash(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - pointer = offset; - r.child_order = new int32[](counters[1]); - - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_child_order(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_child_size(pointer, bs, nil(), counters); - } - else if (fieldId == 3) { - pointer += _read_min_prefix_length(pointer, bs, nil(), counters); - } - else if (fieldId == 4) { - pointer += _read_max_prefix_length(pointer, bs, nil(), counters); - } - else if (fieldId == 5) { - pointer += _read_empty_child(pointer, bs, nil(), counters); - } - else if (fieldId == 6) { - pointer += _read_hash(pointer, bs, nil(), counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_child_order( - uint256 p, - bytes memory bs, - Data memory r, - uint[7] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.child_order[r.child_order.length - counters[1]] = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_child_size( - uint256 p, - bytes memory bs, - Data memory r, - uint[7] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.child_size = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_min_prefix_length( - uint256 p, - bytes memory bs, - Data memory r, - uint[7] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.min_prefix_length = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_max_prefix_length( - uint256 p, - bytes memory bs, - Data memory r, - uint[7] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.max_prefix_length = x; - if (counters[4] > 0) counters[4] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_empty_child( - uint256 p, - bytes memory bs, - Data memory r, - uint[7] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[5] += 1; - } else { - r.empty_child = x; - if (counters[5] > 0) counters[5] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_hash( - uint256 p, - bytes memory bs, - Data memory r, - uint[7] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); - PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[6] += 1; - } else { - r.hash = x; - if(counters[6] > 0) counters[6] -= 1; - } - return sz; - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + Data memory r; + uint[7] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_child_order(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_child_size(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_min_prefix_length(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_max_prefix_length(pointer, bs, r, counters); + } + else if (fieldId == 5) { + pointer += _read_empty_child(pointer, bs, r, counters); + } + else if (fieldId == 6) { + pointer += _read_hash(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.child_order = new int32[](counters[1]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_child_order(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_child_size(pointer, bs, nil(), counters); + } + else if (fieldId == 3) { + pointer += _read_min_prefix_length(pointer, bs, nil(), counters); + } + else if (fieldId == 4) { + pointer += _read_max_prefix_length(pointer, bs, nil(), counters); + } + else if (fieldId == 5) { + pointer += _read_empty_child(pointer, bs, nil(), counters); + } + else if (fieldId == 6) { + pointer += _read_hash(pointer, bs, nil(), counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_child_order( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.child_order[r.child_order.length - counters[1]] = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_child_size( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.child_size = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_min_prefix_length( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.min_prefix_length = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_max_prefix_length( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.max_prefix_length = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_empty_child( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[5] += 1; + } else { + r.empty_child = x; + if (counters[5] > 0) counters[5] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r, + uint[7] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + if (isNil(r)) { + counters[6] += 1; + } else { + r.hash = x; + if(counters[6] > 0) counters[6] -= 1; + } + return sz; + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - uint256 i; - if (r.child_order.length != 0) { - for(i = 0; i < r.child_order.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.Varint, - pointer, - bs) - ; - pointer += ProtoBufRuntime._encode_int32(r.child_order[i], pointer, bs); - } - } - if (r.child_size != 0) { - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_int32(r.child_size, pointer, bs); - } - if (r.min_prefix_length != 0) { - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_int32(r.min_prefix_length, pointer, bs); - } - if (r.max_prefix_length != 0) { - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_int32(r.max_prefix_length, pointer, bs); - } - if (r.empty_child.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 5, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.empty_child, pointer, bs); - } - if (uint(r.hash) != 0) { - pointer += ProtoBufRuntime._encode_key( - 6, - ProtoBufRuntime.WireType.Varint, - pointer, - bs - ); - int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); - pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.child_order.length != 0) { + for(i = 0; i < r.child_order.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.Varint, + pointer, + bs) + ; + pointer += ProtoBufRuntime._encode_int32(r.child_order[i], pointer, bs); + } + } + if (r.child_size != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.child_size, pointer, bs); + } + if (r.min_prefix_length != 0) { + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.min_prefix_length, pointer, bs); + } + if (r.max_prefix_length != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_int32(r.max_prefix_length, pointer, bs); + } + if (r.empty_child.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 5, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.empty_child, pointer, bs); + } + if (uint(r.hash) != 0) { + pointer += ProtoBufRuntime._encode_key( + 6, + ProtoBufRuntime.WireType.Varint, + pointer, + bs + ); + int32 _enum_hash = PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash); + pointer += ProtoBufRuntime._encode_enum(_enum_hash, pointer, bs); + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - /** - * First encoded `r` into a temporary array, and encode the actual size used. - * Then copy the temporary array into `bs`. - */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e;uint256 i; - for(i = 0; i < r.child_order.length; i++) { - e += 1 + ProtoBufRuntime._sz_int32(r.child_order[i]); - } - e += 1 + ProtoBufRuntime._sz_int32(r.child_size); - e += 1 + ProtoBufRuntime._sz_int32(r.min_prefix_length); - e += 1 + ProtoBufRuntime._sz_int32(r.max_prefix_length); - e += 1 + ProtoBufRuntime._sz_lendelim(r.empty_child.length); - e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.child_order.length != 0) { - return false; - } - - if (r.child_size != 0) { - return false; - } - - if (r.min_prefix_length != 0) { - return false; - } - - if (r.max_prefix_length != 0) { - return false; - } - - if (r.empty_child.length != 0) { - return false; - } - - if (uint(r.hash) != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.child_order = input.child_order; - output.child_size = input.child_size; - output.min_prefix_length = input.min_prefix_length; - output.max_prefix_length = input.max_prefix_length; - output.empty_child = input.empty_child; - output.hash = input.hash; - - } - - - //array helpers for ChildOrder - /** - * @dev Add value to an array - * @param self The in-memory struct - * @param value The value to add - */ - function addChildOrder(Data memory self, int32 value) internal pure { - /** - * First resize the array. Then add the new element to the end. - */ - int32[] memory tmp = new int32[](self.child_order.length + 1); - for (uint256 i = 0; i < self.child_order.length; i++) { - tmp[i] = self.child_order[i]; - } - tmp[self.child_order.length] = value; - self.child_order = tmp; - } - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - + { /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + * First encoded `r` into a temporary array, and encode the actual size used. + * Then copy the temporary array into `bs`. + */ + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + for(i = 0; i < r.child_order.length; i++) { + e += 1 + ProtoBufRuntime._sz_int32(r.child_order[i]); + } + e += 1 + ProtoBufRuntime._sz_int32(r.child_size); + e += 1 + ProtoBufRuntime._sz_int32(r.min_prefix_length); + e += 1 + ProtoBufRuntime._sz_int32(r.max_prefix_length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.empty_child.length); + e += 1 + ProtoBufRuntime._sz_enum(PROOFS_PROTO_GLOBAL_ENUMS.encode_HashOp(r.hash)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.child_order.length != 0) { + return false; + } + + if (r.child_size != 0) { + return false; + } + + if (r.min_prefix_length != 0) { + return false; + } + + if (r.max_prefix_length != 0) { + return false; + } + + if (r.empty_child.length != 0) { + return false; + } + + if (uint(r.hash) != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.child_order = input.child_order; + output.child_size = input.child_size; + output.min_prefix_length = input.min_prefix_length; + output.max_prefix_length = input.max_prefix_length; + output.empty_child = input.empty_child; + output.hash = input.hash; + + } + + + //array helpers for ChildOrder + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addChildOrder(Data memory self, int32 value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + int32[] memory tmp = new int32[](self.child_order.length + 1); + for (uint256 i = 0; i < self.child_order.length; i++) { + tmp[i] = self.child_order[i]; + } + tmp[self.child_order.length] = value; + self.child_order = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library InnerSpec library BatchProof { - //struct definition - struct Data { - BatchEntry.Data[] entries; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + BatchEntry.Data[] entries; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[2] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_entries(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - pointer = offset; - r.entries = new BatchEntry.Data[](counters[1]); - - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_entries(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_entries( - uint256 p, - bytes memory bs, - Data memory r, - uint[2] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (BatchEntry.Data memory x, uint256 sz) = _decode_BatchEntry(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.entries[r.entries.length - counters[1]] = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_BatchEntry(uint256 p, bytes memory bs) + { + Data memory r; + uint[2] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.entries = new BatchEntry.Data[](counters[1]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_entries( + uint256 p, + bytes memory bs, + Data memory r, + uint[2] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (BatchEntry.Data memory x, uint256 sz) = _decode_BatchEntry(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.entries[r.entries.length - counters[1]] = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_BatchEntry(uint256 p, bytes memory bs) internal pure returns (BatchEntry.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (BatchEntry.Data memory r, ) = BatchEntry._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (BatchEntry.Data memory r, ) = BatchEntry._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - uint256 i; - if (r.entries.length != 0) { - for(i = 0; i < r.entries.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs) - ; - pointer += BatchEntry._encode_nested(r.entries[i], pointer, bs); - } - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.entries.length != 0) { + for(i = 0; i < r.entries.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += BatchEntry._encode_nested(r.entries[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e;uint256 i; - for(i = 0; i < r.entries.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(BatchEntry._estimate(r.entries[i])); - } - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.entries.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - - for(uint256 i1 = 0; i1 < input.entries.length; i1++) { - output.entries.push(input.entries[i1]); - } - - - } - - - //array helpers for Entries - /** - * @dev Add value to an array - * @param self The in-memory struct - * @param value The value to add - */ - function addEntries(Data memory self, BatchEntry.Data memory value) internal pure { - /** - * First resize the array. Then add the new element to the end. - */ - BatchEntry.Data[] memory tmp = new BatchEntry.Data[](self.entries.length + 1); - for (uint256 i = 0; i < self.entries.length; i++) { - tmp[i] = self.entries[i]; - } - tmp[self.entries.length] = value; - self.entries = tmp; - } - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + for(i = 0; i < r.entries.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(BatchEntry._estimate(r.entries[i])); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.entries.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + + for(uint256 i1 = 0; i1 < input.entries.length; i1++) { + output.entries.push(input.entries[i1]); + } + + + } + + + //array helpers for Entries + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addEntries(Data memory self, BatchEntry.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + BatchEntry.Data[] memory tmp = new BatchEntry.Data[](self.entries.length + 1); + for (uint256 i = 0; i < self.entries.length; i++) { + tmp[i] = self.entries[i]; + } + tmp[self.entries.length] = value; + self.entries = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library BatchProof library BatchEntry { - //struct definition - struct Data { - ExistenceProof.Data exist; - NonExistenceProof.Data nonexist; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + ExistenceProof.Data exist; + NonExistenceProof.Data nonexist; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[3] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_exist(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_nonexist(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_exist( - uint256 p, - bytes memory bs, - Data memory r, - uint[3] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.exist = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_nonexist( - uint256 p, - bytes memory bs, - Data memory r, - uint[3] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.nonexist = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_ExistenceProof(uint256 p, bytes memory bs) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_exist(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.exist = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_nonexist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.nonexist = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_ExistenceProof(uint256 p, bytes memory bs) internal pure returns (ExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_NonExistenceProof(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_NonExistenceProof(uint256 p, bytes memory bs) internal pure returns (NonExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); - - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); - e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - ExistenceProof.store(input.exist, output.exist); - NonExistenceProof.store(input.nonexist, output.nonexist); - - } - - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + ExistenceProof.store(input.exist, output.exist); + NonExistenceProof.store(input.nonexist, output.nonexist); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library BatchEntry library CompressedBatchProof { - //struct definition - struct Data { - CompressedBatchEntry.Data[] entries; - InnerOp.Data[] lookup_inners; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + CompressedBatchEntry.Data[] entries; + InnerOp.Data[] lookup_inners; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[3] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_entries(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_lookup_inners(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - pointer = offset; - r.entries = new CompressedBatchEntry.Data[](counters[1]); - r.lookup_inners = new InnerOp.Data[](counters[2]); - - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_entries(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_lookup_inners(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_entries( - uint256 p, - bytes memory bs, - Data memory r, - uint[3] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedBatchEntry.Data memory x, uint256 sz) = _decode_CompressedBatchEntry(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.entries[r.entries.length - counters[1]] = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_lookup_inners( - uint256 p, - bytes memory bs, - Data memory r, - uint[3] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.lookup_inners[r.lookup_inners.length - counters[2]] = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_CompressedBatchEntry(uint256 p, bytes memory bs) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_lookup_inners(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.entries = new CompressedBatchEntry.Data[](counters[1]); + r.lookup_inners = new InnerOp.Data[](counters[2]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_entries(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_lookup_inners(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_entries( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedBatchEntry.Data memory x, uint256 sz) = _decode_CompressedBatchEntry(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.entries[r.entries.length - counters[1]] = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_lookup_inners( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.lookup_inners[r.lookup_inners.length - counters[2]] = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedBatchEntry(uint256 p, bytes memory bs) internal pure returns (CompressedBatchEntry.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (CompressedBatchEntry.Data memory r, ) = CompressedBatchEntry._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_InnerOp(uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedBatchEntry.Data memory r, ) = CompressedBatchEntry._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_InnerOp(uint256 p, bytes memory bs) internal pure returns (InnerOp.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - uint256 i; - if (r.entries.length != 0) { - for(i = 0; i < r.entries.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs) - ; - pointer += CompressedBatchEntry._encode_nested(r.entries[i], pointer, bs); - } - } - if (r.lookup_inners.length != 0) { - for(i = 0; i < r.lookup_inners.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs) - ; - pointer += InnerOp._encode_nested(r.lookup_inners[i], pointer, bs); - } - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.entries.length != 0) { + for(i = 0; i < r.entries.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += CompressedBatchEntry._encode_nested(r.entries[i], pointer, bs); + } + } + if (r.lookup_inners.length != 0) { + for(i = 0; i < r.lookup_inners.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs) + ; + pointer += InnerOp._encode_nested(r.lookup_inners[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e;uint256 i; - for(i = 0; i < r.entries.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchEntry._estimate(r.entries[i])); - } - for(i = 0; i < r.lookup_inners.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.lookup_inners[i])); - } - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.entries.length != 0) { - return false; - } - - if (r.lookup_inners.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - - for(uint256 i1 = 0; i1 < input.entries.length; i1++) { - output.entries.push(input.entries[i1]); - } - - - for(uint256 i2 = 0; i2 < input.lookup_inners.length; i2++) { - output.lookup_inners.push(input.lookup_inners[i2]); - } - - - } - - - //array helpers for Entries - /** - * @dev Add value to an array - * @param self The in-memory struct - * @param value The value to add - */ - function addEntries(Data memory self, CompressedBatchEntry.Data memory value) internal pure { - /** - * First resize the array. Then add the new element to the end. - */ - CompressedBatchEntry.Data[] memory tmp = new CompressedBatchEntry.Data[](self.entries.length + 1); - for (uint256 i = 0; i < self.entries.length; i++) { - tmp[i] = self.entries[i]; - } - tmp[self.entries.length] = value; - self.entries = tmp; - } - - //array helpers for LookupInners - /** - * @dev Add value to an array - * @param self The in-memory struct - * @param value The value to add - */ - function addLookupInners(Data memory self, InnerOp.Data memory value) internal pure { - /** - * First resize the array. Then add the new element to the end. - */ - InnerOp.Data[] memory tmp = new InnerOp.Data[](self.lookup_inners.length + 1); - for (uint256 i = 0; i < self.lookup_inners.length; i++) { - tmp[i] = self.lookup_inners[i]; - } - tmp[self.lookup_inners.length] = value; - self.lookup_inners = tmp; - } - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + for(i = 0; i < r.entries.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchEntry._estimate(r.entries[i])); + } + for(i = 0; i < r.lookup_inners.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.lookup_inners[i])); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.entries.length != 0) { + return false; + } + + if (r.lookup_inners.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + + for(uint256 i1 = 0; i1 < input.entries.length; i1++) { + output.entries.push(input.entries[i1]); + } + + + for(uint256 i2 = 0; i2 < input.lookup_inners.length; i2++) { + output.lookup_inners.push(input.lookup_inners[i2]); + } + + + } + + + //array helpers for Entries + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addEntries(Data memory self, CompressedBatchEntry.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + CompressedBatchEntry.Data[] memory tmp = new CompressedBatchEntry.Data[](self.entries.length + 1); + for (uint256 i = 0; i < self.entries.length; i++) { + tmp[i] = self.entries[i]; + } + tmp[self.entries.length] = value; + self.entries = tmp; + } + + //array helpers for LookupInners + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addLookupInners(Data memory self, InnerOp.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + InnerOp.Data[] memory tmp = new InnerOp.Data[](self.lookup_inners.length + 1); + for (uint256 i = 0; i < self.lookup_inners.length; i++) { + tmp[i] = self.lookup_inners[i]; + } + tmp[self.lookup_inners.length] = value; + self.lookup_inners = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library CompressedBatchProof library CompressedBatchEntry { - //struct definition - struct Data { - CompressedExistenceProof.Data exist; - CompressedNonExistenceProof.Data nonexist; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + CompressedExistenceProof.Data exist; + CompressedNonExistenceProof.Data nonexist; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[3] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_exist(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_nonexist(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_exist( - uint256 p, - bytes memory bs, - Data memory r, - uint[3] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.exist = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_nonexist( - uint256 p, - bytes memory bs, - Data memory r, - uint[3] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedNonExistenceProof.Data memory x, uint256 sz) = _decode_CompressedNonExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.nonexist = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) + { + Data memory r; + uint[3] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_exist(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.exist = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_nonexist( + uint256 p, + bytes memory bs, + Data memory r, + uint[3] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedNonExistenceProof.Data memory x, uint256 sz) = _decode_CompressedNonExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.nonexist = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) internal - pure - returns (CompressedExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_CompressedNonExistenceProof(uint256 p, bytes memory bs) + pure + returns (CompressedExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedNonExistenceProof(uint256 p, bytes memory bs) internal pure returns (CompressedNonExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (CompressedNonExistenceProof.Data memory r, ) = CompressedNonExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedNonExistenceProof.Data memory r, ) = CompressedNonExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += CompressedExistenceProof._encode_nested(r.exist, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += CompressedNonExistenceProof._encode_nested(r.nonexist, pointer, bs); - - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedNonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.exist)); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedNonExistenceProof._estimate(r.nonexist)); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - CompressedExistenceProof.store(input.exist, output.exist); - CompressedNonExistenceProof.store(input.nonexist, output.nonexist); - - } - - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedNonExistenceProof._estimate(r.nonexist)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + CompressedExistenceProof.store(input.exist, output.exist); + CompressedNonExistenceProof.store(input.nonexist, output.nonexist); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library CompressedBatchEntry library CompressedExistenceProof { - //struct definition - struct Data { - bytes key; - bytes value; - LeafOp.Data leaf; - int32[] path; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + bytes key; + bytes value; + LeafOp.Data leaf; + int32[] path; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[5] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - pointer = offset; - r.path = new int32[](counters[4]); - - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, nil(), counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, nil(), counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_key( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_value( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.value = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_leaf( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.leaf = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_path( - uint256 p, - bytes memory bs, - Data memory r, - uint[5] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.path[r.path.length - counters[4]] = x; - if (counters[4] > 0) counters[4] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_LeafOp(uint256 p, bytes memory bs) + { + Data memory r; + uint[5] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, r, counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, nil(), counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + pointer = offset; + r.path = new int32[](counters[4]); + + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, nil(), counters); + } + else if (fieldId == 2) { + pointer += _read_value(pointer, bs, nil(), counters); + } + else if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, nil(), counters); + } + else if (fieldId == 4) { + pointer += _read_path(pointer, bs, r, counters); + } + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_value( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.value = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_leaf( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.leaf = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_path( + uint256 p, + bytes memory bs, + Data memory r, + uint[5] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + if (isNil(r)) { + counters[4] += 1; + } else { + r.path[r.path.length - counters[4]] = x; + if (counters[4] > 0) counters[4] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_LeafOp(uint256 p, bytes memory bs) internal pure returns (LeafOp.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - uint256 i; - if (r.key.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); - } - if (r.value.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); - } - - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += LeafOp._encode_nested(r.leaf, pointer, bs); - - if (r.path.length != 0) { - for(i = 0; i < r.path.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.Varint, - pointer, - bs) - ; - pointer += ProtoBufRuntime._encode_int32(r.path[i], pointer, bs); - } - } - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + uint256 i; + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + if (r.value.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.value, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += LeafOp._encode_nested(r.leaf, pointer, bs); + + if (r.path.length != 0) { + for(i = 0; i < r.path.length; i++) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.Varint, + pointer, + bs) + ; + pointer += ProtoBufRuntime._encode_int32(r.path[i], pointer, bs); + } + } + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e;uint256 i; - e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); - e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); - e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); - for(i = 0; i < r.path.length; i++) { - e += 1 + ProtoBufRuntime._sz_int32(r.path[i]); - } - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.key.length != 0) { - return false; - } - - if (r.value.length != 0) { - return false; - } - - if (r.path.length != 0) { - return false; - } - - return true; - } - - - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.key = input.key; - output.value = input.value; - LeafOp.store(input.leaf, output.leaf); - output.path = input.path; - - } - - - //array helpers for Path - /** - * @dev Add value to an array - * @param self The in-memory struct - * @param value The value to add - */ - function addPath(Data memory self, int32 value) internal pure { - /** - * First resize the array. Then add the new element to the end. - */ - int32[] memory tmp = new int32[](self.path.length + 1); - for (uint256 i = 0; i < self.path.length; i++) { - tmp[i] = self.path[i]; - } - tmp[self.path.length] = value; - self.path = tmp; - } - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } - } - - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e;uint256 i; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); + e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); + for(i = 0; i < r.path.length; i++) { + e += 1 + ProtoBufRuntime._sz_int32(r.path[i]); + } + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + if (r.value.length != 0) { + return false; + } + + if (r.path.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + output.value = input.value; + LeafOp.store(input.leaf, output.leaf); + output.path = input.path; + + } + + + //array helpers for Path + /** + * @dev Add value to an array + * @param self The in-memory struct + * @param value The value to add + */ + function addPath(Data memory self, int32 value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + int32[] memory tmp = new int32[](self.path.length + 1); + for (uint256 i = 0; i < self.path.length; i++) { + tmp[i] = self.path[i]; + } + tmp[self.path.length] = value; + self.path = tmp; + } + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } } //library CompressedExistenceProof library CompressedNonExistenceProof { - //struct definition - struct Data { - bytes key; - CompressedExistenceProof.Data left; - CompressedExistenceProof.Data right; - } - - // Decoder section - - /** - * @dev The main decoder for memory - * @param bs The bytes array to be decoded - * @return The decoded struct - */ - function decode(bytes memory bs) internal pure returns (Data memory) { - (Data memory x, ) = _decode(32, bs, bs.length); - return x; - } - - /** - * @dev The main decoder for storage - * @param self The in-storage struct - * @param bs The bytes array to be decoded - */ - function decode(Data storage self, bytes memory bs) internal { - (Data memory x, ) = _decode(32, bs, bs.length); - store(x, self); - } - // inner decoder - - /** - * @dev The decoder for internal usage - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param sz The number of bytes expected - * @return The decoded struct - * @return The number of bytes decoded - */ - function _decode(uint256 p, bytes memory bs, uint256 sz) + //struct definition + struct Data { + bytes key; + CompressedExistenceProof.Data left; + CompressedExistenceProof.Data right; + } + + // Decoder section + + /** + * @dev The main decoder for memory + * @param bs The bytes array to be decoded + * @return The decoded struct + */ + function decode(bytes memory bs) internal pure returns (Data memory) { + (Data memory x, ) = _decode(32, bs, bs.length); + return x; + } + + /** + * @dev The main decoder for storage + * @param self The in-storage struct + * @param bs The bytes array to be decoded + */ + function decode(Data storage self, bytes memory bs) internal { + (Data memory x, ) = _decode(32, bs, bs.length); + store(x, self); + } + // inner decoder + + /** + * @dev The decoder for internal usage + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param sz The number of bytes expected + * @return The decoded struct + * @return The number of bytes decoded + */ + function _decode(uint256 p, bytes memory bs, uint256 sz) internal pure returns (Data memory, uint) - { - Data memory r; - uint[4] memory counters; - uint256 fieldId; - ProtoBufRuntime.WireType wireType; - uint256 bytesRead; - uint256 offset = p; - uint256 pointer = p; - while (pointer < offset + sz) { - (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); - pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_left(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_right(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } - } - - } - return (r, sz); - } - - // field readers - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_key( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_left( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.left = x; - if (counters[2] > 0) counters[2] -= 1; - } - return sz; - } - - /** - * @dev The decoder for reading a field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @param r The in-memory struct - * @param counters The counters for repeated fields - * @return The number of bytes decoded - */ - function _read_right( - uint256 p, - bytes memory bs, - Data memory r, - uint[4] memory counters - ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.right = x; - if (counters[3] > 0) counters[3] -= 1; - } - return sz; - } - - // struct decoder - /** - * @dev The decoder for reading a inner struct field - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The decoded inner-struct - * @return The number of bytes used to decode - */ - function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) + { + Data memory r; + uint[4] memory counters; + uint256 fieldId; + ProtoBufRuntime.WireType wireType; + uint256 bytesRead; + uint256 offset = p; + uint256 pointer = p; + while (pointer < offset + sz) { + (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); + pointer += bytesRead; + if (fieldId == 1) { + pointer += _read_key(pointer, bs, r, counters); + } + else if (fieldId == 2) { + pointer += _read_left(pointer, bs, r, counters); + } + else if (fieldId == 3) { + pointer += _read_right(pointer, bs, r, counters); + } + + else { + if (wireType == ProtoBufRuntime.WireType.Fixed64) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Fixed32) { + uint256 size; + (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.Varint) { + uint256 size; + (, size) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += size; + } + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + uint256 size; + (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); + pointer += size; + } + } + + } + return (r, sz); + } + + // field readers + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + if (isNil(r)) { + counters[1] += 1; + } else { + r.key = x; + if (counters[1] > 0) counters[1] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_left( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); + if (isNil(r)) { + counters[2] += 1; + } else { + r.left = x; + if (counters[2] > 0) counters[2] -= 1; + } + return sz; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_right( + uint256 p, + bytes memory bs, + Data memory r, + uint[4] memory counters + ) internal pure returns (uint) { + /** + * if `r` is NULL, then only counting the number of fields. + */ + (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); + if (isNil(r)) { + counters[3] += 1; + } else { + r.right = x; + if (counters[3] > 0) counters[3] -= 1; + } + return sz; + } + + // struct decoder + /** + * @dev The decoder for reading a inner struct field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The decoded inner-struct + * @return The number of bytes used to decode + */ + function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) internal pure returns (CompressedExistenceProof.Data memory, uint) - { - uint256 pointer = p; - (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += bytesRead; - (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); - return (r, sz + bytesRead); - } - - - // Encoder section - - /** - * @dev The main encoder for memory - * @param r The struct to be encoded - * @return The encoded byte array - */ - function encode(Data memory r) internal pure returns (bytes memory) { - bytes memory bs = new bytes(_estimate(r)); - uint256 sz = _encode(r, 32, bs); - assembly { - mstore(bs, sz) - } - return bs; - } - // inner encoder - - /** - * @dev The encoder for internal usage - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode(Data memory r, uint256 p, bytes memory bs) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); + return (r, sz + bytesRead); + } + + + // Encoder section + + /** + * @dev The main encoder for memory + * @param r The struct to be encoded + * @return The encoded byte array + */ + function encode(Data memory r) internal pure returns (bytes memory) { + bytes memory bs = new bytes(_estimate(r)); + uint256 sz = _encode(r, 32, bs); + assembly { + mstore(bs, sz) + } + return bs; + } + // inner encoder + + /** + * @dev The encoder for internal usage + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { - uint256 offset = p; - uint256 pointer = p; - - if (r.key.length != 0) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); - } - - pointer += ProtoBufRuntime._encode_key( - 2, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += CompressedExistenceProof._encode_nested(r.left, pointer, bs); - - - pointer += ProtoBufRuntime._encode_key( - 3, - ProtoBufRuntime.WireType.LengthDelim, - pointer, - bs - ); - pointer += CompressedExistenceProof._encode_nested(r.right, pointer, bs); - - return pointer - offset; - } - // nested encoder - - /** - * @dev The encoder for inner struct - * @param r The struct to be encoded - * @param p The offset of bytes array to start decode - * @param bs The bytes array to be decoded - * @return The number of bytes encoded - */ - function _encode_nested(Data memory r, uint256 p, bytes memory bs) + { + uint256 offset = p; + uint256 pointer = p; + + if (r.key.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_bytes(r.key, pointer, bs); + } + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedExistenceProof._encode_nested(r.left, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += CompressedExistenceProof._encode_nested(r.right, pointer, bs); + + return pointer - offset; + } + // nested encoder + + /** + * @dev The encoder for inner struct + * @param r The struct to be encoded + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @return The number of bytes encoded + */ + function _encode_nested(Data memory r, uint256 p, bytes memory bs) internal pure returns (uint) - { + { /** * First encoded `r` into a temporary array, and encode the actual size used. * Then copy the temporary array into `bs`. */ - uint256 offset = p; - uint256 pointer = p; - bytes memory tmp = new bytes(_estimate(r)); - uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); - uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); - uint256 size = _encode(r, 32, tmp); - pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); - ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); - pointer += size; - delete tmp; - return pointer - offset; - } - // estimator - - /** - * @dev The estimator for a struct - * @param r The struct to be encoded - * @return The number of bytes encoded in estimation - */ - function _estimate( - Data memory r - ) internal pure returns (uint) { - uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.left)); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.right)); - return e; - } - // empty checker - - function _empty( - Data memory r - ) internal pure returns (bool) { - - if (r.key.length != 0) { - return false; - } + uint256 offset = p; + uint256 pointer = p; + bytes memory tmp = new bytes(_estimate(r)); + uint256 tmpAddr = ProtoBufRuntime.getMemoryAddress(tmp); + uint256 bsAddr = ProtoBufRuntime.getMemoryAddress(bs); + uint256 size = _encode(r, 32, tmp); + pointer += ProtoBufRuntime._encode_varint(size, pointer, bs); + ProtoBufRuntime.copyBytes(tmpAddr + 32, bsAddr + pointer, size); + pointer += size; + delete tmp; + return pointer - offset; + } + // estimator + + /** + * @dev The estimator for a struct + * @param r The struct to be encoded + * @return The number of bytes encoded in estimation + */ + function _estimate( + Data memory r + ) internal pure returns (uint) { + uint256 e; + e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.right)); + return e; + } + // empty checker + + function _empty( + Data memory r + ) internal pure returns (bool) { + + if (r.key.length != 0) { + return false; + } + + return true; + } + + + //store function + /** + * @dev Store in-memory struct to storage + * @param input The in-memory struct + * @param output The in-storage struct + */ + function store(Data memory input, Data storage output) internal { + output.key = input.key; + CompressedExistenceProof.store(input.left, output.left); + CompressedExistenceProof.store(input.right, output.right); + + } + + + + //utility functions + /** + * @dev Return an empty struct + * @return r The empty struct + */ + function nil() internal pure returns (Data memory r) { + assembly { + r := 0 + } + } + + /** + * @dev Test whether a struct is empty + * @param x The struct to be tested + * @return r True if it is empty + */ + function isNil(Data memory x) internal pure returns (bool r) { + assembly { + r := iszero(x) + } + } +} +//library CompressedNonExistenceProof - return true; - } +library PROOFS_PROTO_GLOBAL_ENUMS { + //enum definition + // Solidity enum definitions + enum HashOp { + NO_HASH, + SHA256, + SHA512, + KECCAK, + RIPEMD160, + BITCOIN, + SHA512_256 + } - //store function - /** - * @dev Store in-memory struct to storage - * @param input The in-memory struct - * @param output The in-storage struct - */ - function store(Data memory input, Data storage output) internal { - output.key = input.key; - CompressedExistenceProof.store(input.left, output.left); - CompressedExistenceProof.store(input.right, output.right); + // Solidity enum encoder + function encode_HashOp(HashOp x) internal pure returns (int32) { + + if (x == HashOp.NO_HASH) { + return 0; } - - - //utility functions - /** - * @dev Return an empty struct - * @return r The empty struct - */ - function nil() internal pure returns (Data memory r) { - assembly { - r := 0 - } + if (x == HashOp.SHA256) { + return 1; } - /** - * @dev Test whether a struct is empty - * @param x The struct to be tested - * @return r True if it is empty - */ - function isNil(Data memory x) internal pure returns (bool r) { - assembly { - r := iszero(x) - } + if (x == HashOp.SHA512) { + return 2; } -} -//library CompressedNonExistenceProof - -library PROOFS_PROTO_GLOBAL_ENUMS { - //enum definition - // Solidity enum definitions - enum HashOp { - NO_HASH, - SHA256, - SHA512, - KECCAK, - RIPEMD160, - BITCOIN, - SHA512_256 + if (x == HashOp.KECCAK) { + return 3; } - - // Solidity enum encoder - function encode_HashOp(HashOp x) internal pure returns (int32) { - - if (x == HashOp.NO_HASH) { - return 0; - } - - if (x == HashOp.SHA256) { - return 1; - } - - if (x == HashOp.SHA512) { - return 2; - } - - if (x == HashOp.KECCAK) { - return 3; - } - - if (x == HashOp.RIPEMD160) { - return 4; - } - - if (x == HashOp.BITCOIN) { - return 5; - } - - if (x == HashOp.SHA512_256) { - return 6; - } - revert(); + if (x == HashOp.RIPEMD160) { + return 4; } + if (x == HashOp.BITCOIN) { + return 5; + } - // Solidity enum decoder - function decode_HashOp(int64 x) internal pure returns (HashOp) { - - if (x == 0) { - return HashOp.NO_HASH; - } + if (x == HashOp.SHA512_256) { + return 6; + } + revert(); + } - if (x == 1) { - return HashOp.SHA256; - } - if (x == 2) { - return HashOp.SHA512; - } + // Solidity enum decoder + function decode_HashOp(int64 x) internal pure returns (HashOp) { + + if (x == 0) { + return HashOp.NO_HASH; + } - if (x == 3) { - return HashOp.KECCAK; - } + if (x == 1) { + return HashOp.SHA256; + } - if (x == 4) { - return HashOp.RIPEMD160; - } + if (x == 2) { + return HashOp.SHA512; + } - if (x == 5) { - return HashOp.BITCOIN; - } + if (x == 3) { + return HashOp.KECCAK; + } - if (x == 6) { - return HashOp.SHA512_256; - } - revert(); + if (x == 4) { + return HashOp.RIPEMD160; } + if (x == 5) { + return HashOp.BITCOIN; + } - // Solidity enum definitions - enum LengthOp { - NO_PREFIX, - VAR_PROTO, - VAR_RLP, - FIXED32_BIG, - FIXED32_LITTLE, - FIXED64_BIG, - FIXED64_LITTLE, - REQUIRE_32_BYTES, - REQUIRE_64_BYTES + if (x == 6) { + return HashOp.SHA512_256; } + revert(); + } - // Solidity enum encoder - function encode_LengthOp(LengthOp x) internal pure returns (int32) { + // Solidity enum definitions + enum LengthOp { + NO_PREFIX, + VAR_PROTO, + VAR_RLP, + FIXED32_BIG, + FIXED32_LITTLE, + FIXED64_BIG, + FIXED64_LITTLE, + REQUIRE_32_BYTES, + REQUIRE_64_BYTES + } - if (x == LengthOp.NO_PREFIX) { - return 0; - } - if (x == LengthOp.VAR_PROTO) { - return 1; - } + // Solidity enum encoder + function encode_LengthOp(LengthOp x) internal pure returns (int32) { + + if (x == LengthOp.NO_PREFIX) { + return 0; + } - if (x == LengthOp.VAR_RLP) { - return 2; - } + if (x == LengthOp.VAR_PROTO) { + return 1; + } - if (x == LengthOp.FIXED32_BIG) { - return 3; - } + if (x == LengthOp.VAR_RLP) { + return 2; + } - if (x == LengthOp.FIXED32_LITTLE) { - return 4; - } + if (x == LengthOp.FIXED32_BIG) { + return 3; + } - if (x == LengthOp.FIXED64_BIG) { - return 5; - } + if (x == LengthOp.FIXED32_LITTLE) { + return 4; + } - if (x == LengthOp.FIXED64_LITTLE) { - return 6; - } + if (x == LengthOp.FIXED64_BIG) { + return 5; + } - if (x == LengthOp.REQUIRE_32_BYTES) { - return 7; - } + if (x == LengthOp.FIXED64_LITTLE) { + return 6; + } - if (x == LengthOp.REQUIRE_64_BYTES) { - return 8; - } - revert(); + if (x == LengthOp.REQUIRE_32_BYTES) { + return 7; } + if (x == LengthOp.REQUIRE_64_BYTES) { + return 8; + } + revert(); + } - // Solidity enum decoder - function decode_LengthOp(int64 x) internal pure returns (LengthOp) { - if (x == 0) { - return LengthOp.NO_PREFIX; - } + // Solidity enum decoder + function decode_LengthOp(int64 x) internal pure returns (LengthOp) { + + if (x == 0) { + return LengthOp.NO_PREFIX; + } - if (x == 1) { - return LengthOp.VAR_PROTO; - } + if (x == 1) { + return LengthOp.VAR_PROTO; + } - if (x == 2) { - return LengthOp.VAR_RLP; - } + if (x == 2) { + return LengthOp.VAR_RLP; + } - if (x == 3) { - return LengthOp.FIXED32_BIG; - } + if (x == 3) { + return LengthOp.FIXED32_BIG; + } - if (x == 4) { - return LengthOp.FIXED32_LITTLE; - } + if (x == 4) { + return LengthOp.FIXED32_LITTLE; + } - if (x == 5) { - return LengthOp.FIXED64_BIG; - } + if (x == 5) { + return LengthOp.FIXED64_BIG; + } - if (x == 6) { - return LengthOp.FIXED64_LITTLE; - } + if (x == 6) { + return LengthOp.FIXED64_LITTLE; + } - if (x == 7) { - return LengthOp.REQUIRE_32_BYTES; - } + if (x == 7) { + return LengthOp.REQUIRE_32_BYTES; + } - if (x == 8) { - return LengthOp.REQUIRE_64_BYTES; - } - revert(); + if (x == 8) { + return LengthOp.REQUIRE_64_BYTES; } + revert(); + } } //library PROOFS_PROTO_GLOBAL_ENUMS diff --git a/sol/tests/helpers.py b/sol/tests/helpers.py index fe9097b5..f3633e71 100644 --- a/sol/tests/helpers.py +++ b/sol/tests/helpers.py @@ -22,7 +22,6 @@ def loadBatchFile(f, contract): for item in case["items"] ] } - print(to_bytes(case.get("proof", b''), "bytes")) proof = contract.protobufDecodeCommitmentProof(to_bytes(case.get("proof", b''), "bytes")) return proof, refData From 2ce6204405b60de138e21a0ca9848921e1bd4d1c Mon Sep 17 00:00:00 2001 From: Giulio Date: Tue, 14 Dec 2021 09:47:51 +0100 Subject: [PATCH 4/7] 3rd round of review Separating Mock contracts from libraries --- sol/contracts/ics23.sol | 22 +------------------- sol/contracts/ics23Compress.sol | 10 +-------- sol/contracts/ics23CompressMock.sol | 12 +++++++++++ sol/contracts/ics23Mock.sol | 26 +++++++++++++++++++++++ sol/contracts/ics23Ops.sol | 29 -------------------------- sol/contracts/ics23OpsMock.sol | 32 +++++++++++++++++++++++++++++ sol/contracts/ics23Proof.sol | 24 ---------------------- sol/contracts/ics23ProofMock.sol | 25 ++++++++++++++++++++++ sol/tests/test_ics23compress.py | 6 +++--- sol/tests/test_ics23ops.py | 4 ++-- sol/tests/test_ics23proof.py | 4 ++-- sol/tests/test_ics23vectors.py | 6 +++--- 12 files changed, 107 insertions(+), 93 deletions(-) create mode 100644 sol/contracts/ics23CompressMock.sol create mode 100644 sol/contracts/ics23Mock.sol create mode 100644 sol/contracts/ics23OpsMock.sol create mode 100644 sol/contracts/ics23ProofMock.sol diff --git a/sol/contracts/ics23.sol b/sol/contracts/ics23.sol index 16e041f5..68f7cac7 100644 --- a/sol/contracts/ics23.sol +++ b/sol/contracts/ics23.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; + import {BatchProof, CompressedBatchProof, CommitmentProof, ProofSpec, ExistenceProof, NonExistenceProof} from "./proofs.sol"; import {Compress} from "./ics23Compress.sol"; import {Proof} from "./ics23Proof.sol"; @@ -104,24 +105,3 @@ library Ics23 { return ExistenceProof._empty(right) || Ops.compare(right.key, key) > 0; } } - - -contract ICS23_UnitTest { - function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) public pure { - Ics23.VerifyMembershipError vCode = Ics23.verifyMembership(spec, commitmentRoot, proof, key, value); - require(vCode == Ics23.VerifyMembershipError.None); - } - function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) public pure { - Ics23.VerifyNonMembershipError vCode = Ics23.verifyNonMembership(spec, commitmentRoot, proof, key); - require(vCode == Ics23.VerifyNonMembershipError.None); - } -/* -- temporarily disabled as they are not covered by unit tests - function batchVerifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, Ics23.BatchItem[] memory items ) public pure { - Ics23.batchVerifyMembership(spec, commitmentRoot, proof, items); - } - function batchVerifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes[] memory keys ) public pure { - Ics23.batchVerifyNonMembership(spec, commitmentRoot, proof, keys); - } -*/ -} - diff --git a/sol/contracts/ics23Compress.sol b/sol/contracts/ics23Compress.sol index 173934f3..113b429e 100644 --- a/sol/contracts/ics23Compress.sol +++ b/sol/contracts/ics23Compress.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; + import {InnerOp, ExistenceProof, NonExistenceProof, CommitmentProof, CompressedBatchEntry, CompressedBatchProof, CompressedExistenceProof, BatchEntry, BatchProof} from "./proofs.sol"; import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; @@ -65,12 +66,3 @@ library Compress { return decoProof; } } - - - - -contract Compress_UnitTest { - function decompress(CommitmentProof.Data memory proof) public pure returns(CommitmentProof.Data memory) { - return Compress.decompress(proof); - } -} diff --git a/sol/contracts/ics23CompressMock.sol b/sol/contracts/ics23CompressMock.sol new file mode 100644 index 00000000..f8a6bde9 --- /dev/null +++ b/sol/contracts/ics23CompressMock.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +import {CommitmentProof} from "./proofs.sol"; +import {Compress} from "./ics23Compress.sol"; + + +contract CompressMock { + function decompress(CommitmentProof.Data memory proof) public pure returns(CommitmentProof.Data memory) { + return Compress.decompress(proof); + } +} diff --git a/sol/contracts/ics23Mock.sol b/sol/contracts/ics23Mock.sol new file mode 100644 index 00000000..92c7f1af --- /dev/null +++ b/sol/contracts/ics23Mock.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +import {BatchProof, CompressedBatchProof, CommitmentProof, ProofSpec, ExistenceProof, NonExistenceProof} from "./proofs.sol"; +import {Ics23} from "./ics23.sol"; + + +contract ICS23Mock { + function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) public pure { + Ics23.VerifyMembershipError vCode = Ics23.verifyMembership(spec, commitmentRoot, proof, key, value); + require(vCode == Ics23.VerifyMembershipError.None); + } + function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) public pure { + Ics23.VerifyNonMembershipError vCode = Ics23.verifyNonMembership(spec, commitmentRoot, proof, key); + require(vCode == Ics23.VerifyNonMembershipError.None); + } +/* -- temporarily disabled as they are not covered by unit tests + function batchVerifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, Ics23.BatchItem[] memory items ) public pure { + Ics23.batchVerifyMembership(spec, commitmentRoot, proof, items); + } + function batchVerifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes[] memory keys ) public pure { + Ics23.batchVerifyNonMembership(spec, commitmentRoot, proof, keys); + } +*/ +} + diff --git a/sol/contracts/ics23Ops.sol b/sol/contracts/ics23Ops.sol index 27196e6d..3208831e 100644 --- a/sol/contracts/ics23Ops.sol +++ b/sol/contracts/ics23Ops.sol @@ -222,32 +222,3 @@ library Ops { return BytesLib.equal(prefix, slice); } } - - - - -contract Ops_UnitTest { - function applyLeafOp(LeafOp.Data memory leaf, bytes memory key, bytes memory value) public pure returns(bytes memory) { - (bytes memory res, Ops.ApplyLeafOpError aCode) = Ops.applyOp(leaf, key, value); - require(aCode == Ops.ApplyLeafOpError.None); // dev: expand this require to check error code - return res; - } - function checkAgainstLeafOpSpec(LeafOp.Data memory op, ProofSpec.Data memory spec) public pure { - Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); - require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code - } - function applyInnerOp(InnerOp.Data memory inner,bytes memory child) public pure returns(bytes memory) { - (bytes memory res, Ops.ApplyInnerOpError aCode) = Ops.applyOp(inner, child); - require(aCode == Ops.ApplyInnerOpError.None); // dev: expand this require to check error code - return res; - } - function checkAgainstInnerOpSpec(InnerOp.Data memory op, ProofSpec.Data memory spec) public pure { - Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); - require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code - } - function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) public pure returns(bytes memory) { - (bytes memory res, Ops.DoHashError hCode) = Ops.doHash(hashOp, preImage); - require(hCode == Ops.DoHashError.None); // dev: expand this require to check error code - return res; - } -} diff --git a/sol/contracts/ics23OpsMock.sol b/sol/contracts/ics23OpsMock.sol new file mode 100644 index 00000000..cf95859d --- /dev/null +++ b/sol/contracts/ics23OpsMock.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +import {Ops} from "./ics23Ops.sol"; +import {LeafOp, InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, ProofSpec} from "./proofs.sol"; + + +contract OpsMock { + function applyLeafOp(LeafOp.Data memory leaf, bytes memory key, bytes memory value) public pure returns(bytes memory) { + (bytes memory res, Ops.ApplyLeafOpError aCode) = Ops.applyOp(leaf, key, value); + require(aCode == Ops.ApplyLeafOpError.None); // dev: expand this require to check error code + return res; + } + function checkAgainstLeafOpSpec(LeafOp.Data memory op, ProofSpec.Data memory spec) public pure { + Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); + require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code + } + function applyInnerOp(InnerOp.Data memory inner,bytes memory child) public pure returns(bytes memory) { + (bytes memory res, Ops.ApplyInnerOpError aCode) = Ops.applyOp(inner, child); + require(aCode == Ops.ApplyInnerOpError.None); // dev: expand this require to check error code + return res; + } + function checkAgainstInnerOpSpec(InnerOp.Data memory op, ProofSpec.Data memory spec) public pure { + Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); + require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code + } + function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) public pure returns(bytes memory) { + (bytes memory res, Ops.DoHashError hCode) = Ops.doHash(hashOp, preImage); + require(hCode == Ops.DoHashError.None); // dev: expand this require to check error code + return res; + } +} diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol index f5fae402..d50351fc 100644 --- a/sol/contracts/ics23Proof.sol +++ b/sol/contracts/ics23Proof.sol @@ -305,27 +305,3 @@ library Proof{ return slice; } } - - - - -contract Proof_UnitTest { - function calculateExistenceProofRoot(ExistenceProof.Data memory proof) public pure returns(bytes memory) { - (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); - require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code - return res; - } - function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) public pure { - Proof.CheckAgainstSpecError cCode = Proof.checkAgainstSpec(proof, spec); - require(cCode == Proof.CheckAgainstSpecError.None); // dev: expand this require to check error code - } - function calculateCommitmentProofRoot(CommitmentProof.Data memory proof) public pure returns(bytes memory) { - (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); - require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code - return res; - } - function protobufDecodeCommitmentProof(bytes memory msg) public pure returns(CommitmentProof.Data memory) { - CommitmentProof.Data memory res = CommitmentProof.decode(msg); - return res; - } -} diff --git a/sol/contracts/ics23ProofMock.sol b/sol/contracts/ics23ProofMock.sol new file mode 100644 index 00000000..c064313b --- /dev/null +++ b/sol/contracts/ics23ProofMock.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; +import {Proof} from "./ics23Proof.sol"; +import { ExistenceProof, ProofSpec, CommitmentProof} from "./proofs.sol"; + +contract ProofMock { + function calculateExistenceProofRoot(ExistenceProof.Data memory proof) public pure returns(bytes memory) { + (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); + require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code + return res; + } + function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) public pure { + Proof.CheckAgainstSpecError cCode = Proof.checkAgainstSpec(proof, spec); + require(cCode == Proof.CheckAgainstSpecError.None); // dev: expand this require to check error code + } + function calculateCommitmentProofRoot(CommitmentProof.Data memory proof) public pure returns(bytes memory) { + (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); + require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code + return res; + } + function protobufDecodeCommitmentProof(bytes memory msg) public pure returns(CommitmentProof.Data memory) { + CommitmentProof.Data memory res = CommitmentProof.decode(msg); + return res; + } +} diff --git a/sol/tests/test_ics23compress.py b/sol/tests/test_ics23compress.py index 74b73bd7..fdcff8c3 100644 --- a/sol/tests/test_ics23compress.py +++ b/sol/tests/test_ics23compress.py @@ -1,4 +1,4 @@ -from brownie import accounts, Compress_UnitTest, Proof_UnitTest +from brownie import accounts, CompressMock, ProofMock from brownie.convert import to_bytes import pytest import specs @@ -13,12 +13,12 @@ @pytest.fixture def compress(): - return accounts[0].deploy(Compress_UnitTest) + return accounts[0].deploy(CompressMock) @pytest.fixture def proof(): - return accounts[0].deploy(Proof_UnitTest) + return accounts[0].deploy(ProofMock) @pytest.mark.parametrize("fname", [os.path.join(IAVL_TEST_DIR, fname) for fname in cases_fname]) diff --git a/sol/tests/test_ics23ops.py b/sol/tests/test_ics23ops.py index 5ca57c43..a1ff8cf4 100644 --- a/sol/tests/test_ics23ops.py +++ b/sol/tests/test_ics23ops.py @@ -1,4 +1,4 @@ -from brownie import accounts, Ops_UnitTest +from brownie import accounts, OpsMock from brownie.convert import to_bytes, to_string import brownie import pytest @@ -9,7 +9,7 @@ @pytest.fixture def ops(): - return accounts[0].deploy(Ops_UnitTest) + return accounts[0].deploy(OpsMock) @pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestLeafOpData.json")) diff --git a/sol/tests/test_ics23proof.py b/sol/tests/test_ics23proof.py index af89e59c..e31591f2 100644 --- a/sol/tests/test_ics23proof.py +++ b/sol/tests/test_ics23proof.py @@ -1,4 +1,4 @@ -from brownie import accounts, Proof_UnitTest +from brownie import accounts, ProofMock from brownie.convert import to_bytes, to_string import brownie import pytest @@ -9,7 +9,7 @@ @pytest.fixture def proof(): - return accounts[0].deploy(Proof_UnitTest) + return accounts[0].deploy(ProofMock) @pytest.mark.parametrize("name,case", helpers.loadJsonTestCases("../testdata/TestExistenceProofData.json")) diff --git a/sol/tests/test_ics23vectors.py b/sol/tests/test_ics23vectors.py index 21e84d20..e4bacb3f 100644 --- a/sol/tests/test_ics23vectors.py +++ b/sol/tests/test_ics23vectors.py @@ -1,4 +1,4 @@ -from brownie import accounts, ICS23_UnitTest, Proof_UnitTest +from brownie import accounts, ICS23Mock, ProofMock from brownie.convert import to_bytes import pytest import specs @@ -13,12 +13,12 @@ @pytest.fixture def ics23(): - return accounts[0].deploy(ICS23_UnitTest) + return accounts[0].deploy(ICS23Mock) @pytest.fixture def proof(): - return accounts[0].deploy(Proof_UnitTest) + return accounts[0].deploy(ProofMock) @pytest.mark.parametrize("fname", [os.path.join(IAVL_TEST_DIR, fname) for fname in cases_fname]) From 36d05877a0e3d1ab03c79dcfe80837ab5d0f3afa Mon Sep 17 00:00:00 2001 From: Giulio Date: Thu, 13 Jan 2022 11:49:41 +0100 Subject: [PATCH 5/7] first round of PR review --- sol/.gitattributes | 2 - sol/contracts/ics23.sol | 2 +- sol/contracts/ics23Compress.sol | 15 ++++- sol/contracts/ics23Ops.sol | 37 +++++++++-- sol/contracts/ics23Proof.sol | 101 ++++++++++++++++++++++++++----- sol/contracts/ics23ProofMock.sol | 4 +- 6 files changed, 133 insertions(+), 28 deletions(-) delete mode 100644 sol/.gitattributes diff --git a/sol/.gitattributes b/sol/.gitattributes deleted file mode 100644 index adb20fe2..00000000 --- a/sol/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -*.sol linguist-language=Solidity -*.vy linguist-language=Python diff --git a/sol/contracts/ics23.sol b/sol/contracts/ics23.sol index 68f7cac7..f2e9727c 100644 --- a/sol/contracts/ics23.sol +++ b/sol/contracts/ics23.sol @@ -14,7 +14,6 @@ library Ics23 { ExistenceProofIsNil, ProofVerify } - // verifyMembership, throws an exception in case anything goes wrong function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) internal pure returns(VerifyMembershipError){ CommitmentProof.Data memory decoProof = Compress.decompress(proof); ExistenceProof.Data memory exiProof = getExistProofForKey(decoProof, key); @@ -31,6 +30,7 @@ library Ics23 { NonExistenceProofIsNil, ProofVerify } + function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) internal pure returns(VerifyNonMembershipError) { CommitmentProof.Data memory decoProof = Compress.decompress(proof); NonExistenceProof.Data memory nonProof = getNonExistProofForKey(decoProof, key); diff --git a/sol/contracts/ics23Compress.sol b/sol/contracts/ics23Compress.sol index 113b429e..ec4d43be 100644 --- a/sol/contracts/ics23Compress.sol +++ b/sol/contracts/ics23Compress.sol @@ -5,6 +5,10 @@ import {InnerOp, ExistenceProof, NonExistenceProof, CommitmentProof, CompressedB import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; library Compress { + /** + @notice will return a BatchProof if the input is CompressedBatchProof. Otherwise it will return the input. + This is safe to call multiple times (idempotent) + */ function decompress(CommitmentProof.Data memory proof) internal pure returns(CommitmentProof.Data memory) { //CompressedBatchProof.isNil() does not work if (CompressedBatchProof._empty(proof.compressed) == true){ @@ -20,7 +24,6 @@ library Compress { }); } - // private function decompress(CompressedBatchProof.Data memory proof) private pure returns(BatchEntry.Data[] memory) { BatchEntry.Data[] memory entries = new BatchEntry.Data[](proof.entries.length); for(uint i = 0; i < proof.entries.length; i++) { @@ -29,7 +32,10 @@ library Compress { return entries; } - function decompressEntry(CompressedBatchEntry.Data memory entry, InnerOp.Data[] memory lookup) private pure returns(BatchEntry.Data memory) { + function decompressEntry( + CompressedBatchEntry.Data memory entry, + InnerOp.Data[] memory lookup + ) private pure returns(BatchEntry.Data memory) { //CompressedExistenceProof.isNil does not work if (CompressedExistenceProof._empty(entry.exist) == false) { return BatchEntry.Data({ @@ -47,7 +53,10 @@ library Compress { }); } - function decompressExist(CompressedExistenceProof.Data memory proof, InnerOp.Data[] memory lookup) private pure returns(ExistenceProof.Data memory) { + function decompressExist( + CompressedExistenceProof.Data memory proof, + InnerOp.Data[] memory lookup + ) private pure returns(ExistenceProof.Data memory) { if (CompressedExistenceProof._empty(proof)) { return ExistenceProof.nil(); } diff --git a/sol/contracts/ics23Ops.sol b/sol/contracts/ics23Ops.sol index 3208831e..801e8565 100644 --- a/sol/contracts/ics23Ops.sol +++ b/sol/contracts/ics23Ops.sol @@ -17,8 +17,15 @@ library Ops { DoHash, PrepareLeafData } - // LeafOp operations - function applyOp(LeafOp.Data memory leafOp, bytes memory key, bytes memory value) internal pure returns(bytes memory, ApplyLeafOpError) { + /** + @notice calculates the leaf hash given the key and value being proven + @return VerifyExistenceError enum giving indication of where error happened, None if verification succeded + */ + function applyOp( + LeafOp.Data memory leafOp, + bytes memory key, + bytes memory value + ) internal pure returns(bytes memory, ApplyLeafOpError) { //require(key.length > 0); // dev: Leaf op needs key if (key.length == 0) return (empty, ApplyLeafOpError.KeyLength); //require(value.length > 0); // dev: Leaf op needs value @@ -38,8 +45,11 @@ library Ops { DoHash, DoLengthOp } - // preapare leaf data for encoding - function prepareLeafData(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) internal pure returns(bytes memory, PrepareLeafDataError) { + function prepareLeafData( + PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, + PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, + bytes memory data + ) internal pure returns(bytes memory, PrepareLeafDataError) { (bytes memory hased, DoHashError hCode) = doHashOrNoop(hashOp, data); if (hCode != DoHashError.None)return (empty, PrepareLeafDataError.DoHash); (bytes memory res, DoLengthOpError lCode) = doLengthOp(lenOp, hased); @@ -58,6 +68,9 @@ library Ops { HasPrefix, MaxPrefixLength } + /** + @notice will verify the LeafOp is in the format defined in spec + */ function checkAgainstSpec(LeafOp.Data memory leafOp, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { //require (leafOp.hash == spec.leaf_spec.hash); // dev: checkAgainstSpec for LeafOp - Unexpected HashOp if (leafOp.hash != spec.leaf_spec.hash) return CheckAgainstSpecError.Hash; @@ -79,7 +92,9 @@ library Ops { ChildLength, DoHash } - // InnerOp operations + /** + @notice apply will calculate the hash of the next step, given the hash of the previous step + */ function applyOp(InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory, ApplyInnerOpError) { //require(child.length > 0); // dev: Inner op needs child value if (child.length == 0) return (empty, ApplyInnerOpError.ChildLength); @@ -90,6 +105,9 @@ library Ops { return (hashed, ApplyInnerOpError.None); } + /** + @notice will verify the InnerOp is in the format defined in spec + */ function checkAgainstSpec(InnerOp.Data memory innerOp, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { //require(innerOp.hash == spec.inner_spec.hash); // dev: checkAgainstSpec for InnerOp - Unexpected HashOp if (innerOp.hash != spec.inner_spec.hash) return CheckAgainstSpecError.Hash; @@ -109,6 +127,9 @@ library Ops { return CheckAgainstSpecError.None; } + /** + @notice will return the preimage untouched if hashOp == NONE, otherwise, perform doHash + */ function doHashOrNoop(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory, DoHashError) { if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.NO_HASH) { return (preImage, DoHashError.None); @@ -122,6 +143,9 @@ library Ops { Sha512_256, Unsupported } + /** + @notice will preform the specified hash on the preimage. If hashOp == NONE, + */ function doHash(PROOFS_PROTO_GLOBAL_ENUMS.HashOp hashOp, bytes memory preImage) internal pure returns(bytes memory, DoHashError) { if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA256) { return (abi.encodePacked(sha256(preImage)), DoHashError.None); @@ -173,6 +197,9 @@ library Ops { Require64DataLength, Unsupported } + /** + @notice will calculate the proper prefix and return it prepended doLengthOp(op, data) -> length(data) || data + */ function doLengthOp(PROOFS_PROTO_GLOBAL_ENUMS.LengthOp lenOp, bytes memory data) private pure returns(bytes memory, DoLengthOpError) { if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.NO_PREFIX) { return (data, DoLengthOpError.None); diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol index d50351fc..badc388f 100644 --- a/sol/contracts/ics23Proof.sol +++ b/sol/contracts/ics23Proof.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {LeafOp, CompressedBatchProof, ExistenceProof, NonExistenceProof, BatchEntry, BatchProof, ProofSpec, InnerOp, InnerSpec, CommitmentProof} from "./proofs.sol"; +import { + LeafOp, CompressedBatchProof, ExistenceProof, NonExistenceProof, BatchEntry, BatchProof, ProofSpec, InnerOp, InnerSpec, CommitmentProof +} from "./proofs.sol"; import {Ops} from "./ics23Ops.sol"; import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol"; @@ -19,15 +21,24 @@ library Proof{ CalculateRoot, RootNotMatching } - // ExistenceProof - function verify(ExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key, bytes memory value) internal pure returns(VerifyExistenceError) { + /** + @notice verify does all checks to ensure this proof proves this key, value -> root and matches the spec. + @return VerifyExistenceError enum giving indication of where error happened, None if verification succeded + */ + function verify( + ExistenceProof.Data memory proof, + ProofSpec.Data memory spec, + bytes memory commitmentRoot, + bytes memory key, + bytes memory value + ) internal pure returns(VerifyExistenceError) { //require(BytesLib.equal(proof.key, key)); // dev: Provided key doesn't match proof bool keyMatch = BytesLib.equal(proof.key, key); if (keyMatch == false) return VerifyExistenceError.KeyNotMatching; //require(BytesLib.equal(proof.value, value)); // dev: Provided value doesn't match proof bool valueMatch = BytesLib.equal(proof.value, value); if (valueMatch == false) return VerifyExistenceError.ValueNotMatching; - CheckAgainstSpecError cCode = checkAgainstSpec(proof, spec); + CheckAgainstSpecError cCode = checkAgainstSpec(proof, spec); if (cCode != CheckAgainstSpecError.None) return VerifyExistenceError.CheckSpec; (bytes memory root, CalculateRootError rCode) = calculateRoot(proof); if (rCode != CalculateRootError.None) return VerifyExistenceError.CalculateRoot; @@ -47,6 +58,10 @@ library Proof{ BatchEntryEmpty, EmptyProof } + /** + @notice calculateRoot determines the root hash that matches the given proof. You must validate the result in what you have in a header. + @return CalculateRootError enum giving indication of where error happened, None if verification succeded + */ function calculateRoot(ExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { //require(LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp if (LeafOp.isNil(proof.leaf)) return (empty, CalculateRootError.LeafNil); @@ -68,6 +83,10 @@ library Proof{ InnerOpsDepthTooShort, InnerOpsDepthTooLong } + /** + @notice checkAgainstSpec will verify the leaf and all path steps are in the format defined in spec + @return CheckAgainstSpecError enum giving indication of where error happened, None if verification succeded + */ function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { // LeafOp.isNil does not work //require(LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp @@ -85,8 +104,8 @@ library Proof{ if (innerOpsDepthTooLong) return CheckAgainstSpecError.InnerOpsDepthTooLong; } for(uint i = 0; i < proof.path.length; i++) { - Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(proof.path[i], spec); - if (cCode != Ops.CheckAgainstSpecError.None) return CheckAgainstSpecError.OpsCheckAgainstSpec; + Ops.CheckAgainstSpecError opscCode = Ops.checkAgainstSpec(proof.path[i], spec); + if (opscCode != Ops.CheckAgainstSpecError.None) return CheckAgainstSpecError.OpsCheckAgainstSpec; } } @@ -101,8 +120,17 @@ library Proof{ LeftProofRightMost, IsLeftNeighbor } - // NonExistenceProof - function verify(NonExistenceProof.Data memory proof, ProofSpec.Data memory spec, bytes memory commitmentRoot,bytes memory key) internal pure returns(VerifyNonExistenceError) { + /** + @notice verify does all checks to ensure the proof has valid non-existence proofs, + and they ensure the given key is not in the CommitmentState + @return VerifyNonExistenceError enum giving indication of where error happened, None if verification succeded + */ + function verify( + NonExistenceProof.Data memory proof, + ProofSpec.Data memory spec, + bytes memory commitmentRoot, + bytes memory key + ) internal pure returns(VerifyNonExistenceError) { bytes memory leftKey; bytes memory rightKey; // ExistenceProof.isNil does not work @@ -145,6 +173,10 @@ library Proof{ return VerifyNonExistenceError.None; } + /** + @notice calculateRoot determines the root hash that matches the given proof. You must validate the result in what you have in a header. + @return CalculateRootError enum giving indication of where error happened, None if verification succeded + */ function calculateRoot(NonExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { if (ExistenceProof._empty(proof.left) == false) { return calculateRoot(proof.left); @@ -156,7 +188,12 @@ library Proof{ return (empty, CalculateRootError.EmptyProof); } - // commitment proof + /** + @notice calculateRoot determines the root hash that matches the given proof by switching and calculating root based on proof type + NOTE: Calculate will return the first calculated root in the proof, you must validate that all other embedded ExistenceProofs + commit to the same root. This can be done with the Verify method + @return CalculateRootError enum giving indication of where error happened, None if verification succeded + */ function calculateRoot(CommitmentProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { if (ExistenceProof._empty(proof.exist) == false) { return calculateRoot(proof.exist); @@ -184,7 +221,9 @@ library Proof{ } - // private + /** + @return true if this is the left-most path in the tree + */ function isLeftMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool) { (uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError gCode) = getPadding(spec, 0); if (gCode != GetPaddingError.None) return false; @@ -196,6 +235,9 @@ library Proof{ return true; } + /** + @return true if this is the right-most path in the tree + */ function isRightMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool){ uint last = spec.child_order.length - 1; (uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError gCode) = getPadding(spec, last); @@ -209,6 +251,9 @@ library Proof{ return true; } + /** + @notice assumes left and right have common parents checks if left is exactly one slot to the left of right + */ function isLeftStep(InnerSpec.Data memory spec, InnerOp.Data memory left, InnerOp.Data memory right) private pure returns(bool){ (uint leftIdx, OrderFromPaddingError lCode) = orderFromPadding(spec, left); if (lCode != OrderFromPaddingError.None) return false; @@ -219,15 +264,25 @@ library Proof{ return rightIdx == leftIdx + 1; } - function isLeftNeighbor(InnerSpec.Data memory spec, InnerOp.Data[] memory left, InnerOp.Data[] memory right) private pure returns(bool) { + /** + @notice find the common suffix from the Left.Path and Right.Path and remove it. We have LPath and RPath now, which must be neighbors. + Validate that LPath[len-1] is the left neighbor of RPath[len-1] + For step in LPath[0..len-1], validate step is right-most node + For step in RPath[0..len-1], validate step is left-most node + */ + function isLeftNeighbor( + InnerSpec.Data memory spec, + InnerOp.Data[] memory left, + InnerOp.Data[] memory right + ) private pure returns(bool) { uint leftIdx = left.length - 1; uint rightIdx = right.length - 1; while (leftIdx >= 0 && rightIdx >= 0) { if (BytesLib.equal(left[leftIdx].prefix, right[rightIdx].prefix) && - BytesLib.equal(left[leftIdx].suffix, right[rightIdx].suffix)) { + BytesLib.equal(left[leftIdx].suffix, right[rightIdx].suffix)) { leftIdx -= 1; - rightIdx -= 1; - continue; + rightIdx -= 1; + continue; } break; } @@ -249,6 +304,9 @@ library Proof{ NotFound, GetPadding } + /** + @notice this will look at the proof and determine which order it is... So we can see if it is branch 0, 1, 2 etc... to determine neighbors + */ function orderFromPadding(InnerSpec.Data memory spec, InnerOp.Data memory op) private pure returns(uint, OrderFromPaddingError) { uint256 maxBranch = spec.child_order.length; for(uint branch = 0; branch < maxBranch; branch++) { @@ -264,7 +322,13 @@ library Proof{ None, GetPosition } - function getPadding(InnerSpec.Data memory spec, uint branch) private pure returns(uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError) { + /** + @notice determines prefix and suffix with the given spec and position in the tree + */ + function getPadding( + InnerSpec.Data memory spec, + uint branch + ) private pure returns(uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError) { uint uChildSize = SafeCast.toUint256(spec.child_size); (uint idx, GetPositionError gCode) = getPosition(spec.child_order, branch); if (gCode != GetPositionError.None) return (0, 0, 0, GetPaddingError.GetPosition); @@ -281,6 +345,10 @@ library Proof{ BranchLength, NoFound } + /** + @notice checks where the branch is in the order and returns the index of this branch + @return GetPositionError enum giving indication of where error happened, None if verification succeded + */ function getPosition(int32[] memory order, uint branch) private pure returns(uint, GetPositionError) { //require(branch < order.length); // dev: invalid branch if (branch >= order.length) return (0, GetPositionError.BranchLength); @@ -297,6 +365,9 @@ library Proof{ return op.suffix.length == suffix; } + /** + @return a slice of of InnerOp.Data, array[start..end] + */ function sliceInnerOps(InnerOp.Data[] memory array, uint start, uint end) private pure returns(InnerOp.Data[] memory) { InnerOp.Data[] memory slice = new InnerOp.Data[](end-start); for (uint i = start; i < end; i++) { diff --git a/sol/contracts/ics23ProofMock.sol b/sol/contracts/ics23ProofMock.sol index c064313b..64178bf3 100644 --- a/sol/contracts/ics23ProofMock.sol +++ b/sol/contracts/ics23ProofMock.sol @@ -18,8 +18,8 @@ contract ProofMock { require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code return res; } - function protobufDecodeCommitmentProof(bytes memory msg) public pure returns(CommitmentProof.Data memory) { - CommitmentProof.Data memory res = CommitmentProof.decode(msg); + function protobufDecodeCommitmentProof(bytes memory protoMsg) public pure returns(CommitmentProof.Data memory) { + CommitmentProof.Data memory res = CommitmentProof.decode(protoMsg); return res; } } From 83f9d68dc5ecab9fe0dce358488a6133445c2752 Mon Sep 17 00:00:00 2001 From: Giulio Date: Mon, 17 Jan 2022 10:48:22 +0100 Subject: [PATCH 6/7] updating with last solidity-protobuf compiler --- sol/contracts/GoogleProtobufAny.sol | 2 +- sol/contracts/ProtoBufRuntime.sol | 96 +- sol/contracts/ics23.sol | 73 +- sol/contracts/ics23Compress.sol | 61 +- sol/contracts/ics23CompressMock.sol | 4 +- sol/contracts/ics23Mock.sol | 19 +- sol/contracts/ics23Ops.sol | 20 +- sol/contracts/ics23OpsMock.sol | 10 +- sol/contracts/ics23Proof.sol | 123 +- sol/contracts/ics23ProofMock.sol | 12 +- sol/contracts/proofs.sol | 1794 +++++++++------------------ 11 files changed, 851 insertions(+), 1363 deletions(-) diff --git a/sol/contracts/GoogleProtobufAny.sol b/sol/contracts/GoogleProtobufAny.sol index 8de3260e..0a0a851f 100644 --- a/sol/contracts/GoogleProtobufAny.sol +++ b/sol/contracts/GoogleProtobufAny.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.2; +pragma solidity ^0.8.10; import "./ProtoBufRuntime.sol"; library GoogleProtobufAny { diff --git a/sol/contracts/ProtoBufRuntime.sol b/sol/contracts/ProtoBufRuntime.sol index 43a86d44..b72bcce6 100644 --- a/sol/contracts/ProtoBufRuntime.sol +++ b/sol/contracts/ProtoBufRuntime.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.2; +pragma solidity ^0.8.10; /** @@ -112,6 +112,10 @@ library ProtoBufRuntime { * @param len The length of bytes to copy */ function copyBytes(uint256 src, uint256 dest, uint256 len) internal pure { + if (len == 0) { + return; + } + // Copy word-length chunks while possible for (; len > WORD_LENGTH; len -= WORD_LENGTH) { assembly { @@ -561,6 +565,32 @@ library ProtoBufRuntime { return (b, sz + len); } + /** + * @dev Skip the decoding of a single field + * @param wt The WireType of the field + * @param p The memory offset of `bs` + * @param bs The bytes array to be decoded + * @return The length of `bs` to skipped + */ + function _skip_field_decode(WireType wt, uint256 p, bytes memory bs) + internal + pure + returns (uint256) + { + if (wt == ProtoBufRuntime.WireType.Fixed64) { + return 8; + } else if (wt == ProtoBufRuntime.WireType.Fixed32) { + return 4; + } else if (wt == ProtoBufRuntime.WireType.Varint) { + (, uint256 size) = ProtoBufRuntime._decode_varint(p, bs); + return size; + } else { + require(wt == ProtoBufRuntime.WireType.LengthDelim); + (uint256 len, uint256 size) = ProtoBufRuntime._decode_varint(p, bs); + return size + len; + } + } + // Encoders /** * @dev Encode ProtoBuf key @@ -936,6 +966,70 @@ library ProtoBufRuntime { return _sz_varint(_encode_zigzag(i)); } + /** + * `_estimate_packed_repeated_(uint32|uint64|int32|int64|sint32|sint64)` + */ + function _estimate_packed_repeated_uint32(uint32[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += _sz_uint32(a[i]); + } + return e; + } + + function _estimate_packed_repeated_uint64(uint64[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += _sz_uint64(a[i]); + } + return e; + } + + function _estimate_packed_repeated_int32(int32[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += _sz_int32(a[i]); + } + return e; + } + + function _estimate_packed_repeated_int64(int64[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += _sz_int64(a[i]); + } + return e; + } + + function _estimate_packed_repeated_sint32(int32[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += _sz_sint32(a[i]); + } + return e; + } + + function _estimate_packed_repeated_sint64(int64[] memory a) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += _sz_sint64(a[i]); + } + return e; + } + + // Element counters for packed repeated fields + function _count_packed_repeated_varint(uint256 p, uint256 len, bytes memory bs) internal pure returns (uint256) { + uint256 count = 0; + uint256 end = p + len; + while (p < end) { + uint256 sz; + (, sz) = _decode_varint(p, bs); + p += sz; + count += 1; + } + return count; + } + // Soltype extensions /** * @dev Decode Solidity integer and/or fixed-size bytes array, filling from lowest bit. diff --git a/sol/contracts/ics23.sol b/sol/contracts/ics23.sol index f2e9727c..47af0400 100644 --- a/sol/contracts/ics23.sol +++ b/sol/contracts/ics23.sol @@ -1,7 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {BatchProof, CompressedBatchProof, CommitmentProof, ProofSpec, ExistenceProof, NonExistenceProof} from "./proofs.sol"; +import { + Ics23BatchProof, Ics23CompressedBatchProof, Ics23CommitmentProof, Ics23ProofSpec, Ics23ExistenceProof, Ics23NonExistenceProof +} from "./proofs.sol"; import {Compress} from "./ics23Compress.sol"; import {Proof} from "./ics23Proof.sol"; import {Ops} from "./ics23Ops.sol"; @@ -14,11 +16,17 @@ library Ics23 { ExistenceProofIsNil, ProofVerify } - function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) internal pure returns(VerifyMembershipError){ - CommitmentProof.Data memory decoProof = Compress.decompress(proof); - ExistenceProof.Data memory exiProof = getExistProofForKey(decoProof, key); - //require(ExistenceProof.isNil(exiProof) == false); // dev: getExistProofForKey not available - if (ExistenceProof.isNil(exiProof)) return VerifyMembershipError.ExistenceProofIsNil; + function verifyMembership( + Ics23ProofSpec.Data memory spec, + bytes memory commitmentRoot, + Ics23CommitmentProof.Data memory proof, + bytes memory key, + bytes memory value + ) internal pure returns(VerifyMembershipError){ + Ics23CommitmentProof.Data memory decoProof = Compress.decompress(proof); + Ics23ExistenceProof.Data memory exiProof = getExistProofForKey(decoProof, key); + //require(Ics23ExistenceProof.isNil(exiProof) == false); // dev: getExistProofForKey not available + if (Ics23ExistenceProof.isNil(exiProof)) return VerifyMembershipError.ExistenceProofIsNil; Proof.VerifyExistenceError vCode = Proof.verify(exiProof, spec, commitmentRoot, key, value); if (vCode != Proof.VerifyExistenceError.None) return VerifyMembershipError.ProofVerify; @@ -31,11 +39,16 @@ library Ics23 { ProofVerify } - function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) internal pure returns(VerifyNonMembershipError) { - CommitmentProof.Data memory decoProof = Compress.decompress(proof); - NonExistenceProof.Data memory nonProof = getNonExistProofForKey(decoProof, key); - //require(NonExistenceProof.isNil(nonProof) == false); // dev: getNonExistProofForKey not available - if (NonExistenceProof.isNil(nonProof)) return VerifyNonMembershipError.NonExistenceProofIsNil; + function verifyNonMembership( + Ics23ProofSpec.Data memory spec, + bytes memory commitmentRoot, + Ics23CommitmentProof.Data memory proof, + bytes memory key + ) internal pure returns(VerifyNonMembershipError) { + Ics23CommitmentProof.Data memory decoProof = Compress.decompress(proof); + Ics23NonExistenceProof.Data memory nonProof = getNonExistProofForKey(decoProof, key); + //require(Ics23NonExistenceProof.isNil(nonProof) == false); // dev: getNonExistProofForKey not available + if (Ics23NonExistenceProof.isNil(nonProof)) return VerifyNonMembershipError.NonExistenceProofIsNil; Proof.VerifyNonExistenceError vCode = Proof.verify(nonProof, spec, commitmentRoot, key); if (vCode != Proof.VerifyNonExistenceError.None) return VerifyNonMembershipError.ProofVerify; @@ -62,46 +75,52 @@ library Ics23 { */ // private - function getExistProofForKey(CommitmentProof.Data memory proof, bytes memory key) private pure returns(ExistenceProof.Data memory) { - if (ExistenceProof.isNil(proof.exist) == false){ + function getExistProofForKey( + Ics23CommitmentProof.Data memory proof, + bytes memory key + ) private pure returns(Ics23ExistenceProof.Data memory) { + if (Ics23ExistenceProof.isNil(proof.exist) == false){ if (BytesLib.equal(proof.exist.key, key) == true) { return proof.exist; } - } else if(BatchProof.isNil(proof.batch) == false) { + } else if(Ics23BatchProof.isNil(proof.batch) == false) { for (uint i = 0; i < proof.batch.entries.length; i++) { - if (ExistenceProof.isNil(proof.batch.entries[i].exist) == false && + if (Ics23ExistenceProof.isNil(proof.batch.entries[i].exist) == false && BytesLib.equal(proof.batch.entries[i].exist.key, key)) { return proof.batch.entries[i].exist; } } } - return ExistenceProof.nil(); + return Ics23ExistenceProof.nil(); } - function getNonExistProofForKey(CommitmentProof.Data memory proof, bytes memory key) private pure returns(NonExistenceProof.Data memory) { - if (NonExistenceProof.isNil(proof.nonexist) == false) { + function getNonExistProofForKey( + Ics23CommitmentProof.Data memory proof, + bytes memory key + ) private pure returns(Ics23NonExistenceProof.Data memory) { + if (Ics23NonExistenceProof.isNil(proof.nonexist) == false) { if (isLeft(proof.nonexist.left, key) && isRight(proof.nonexist.right, key)) { return proof.nonexist; } - } else if (BatchProof.isNil(proof.batch) == false) { + } else if (Ics23BatchProof.isNil(proof.batch) == false) { for (uint i = 0; i < proof.batch.entries.length; i++) { - if (NonExistenceProof.isNil(proof.batch.entries[i].nonexist) == false && + if (Ics23NonExistenceProof.isNil(proof.batch.entries[i].nonexist) == false && isLeft(proof.batch.entries[i].nonexist.left, key) && isRight(proof.batch.entries[i].nonexist.right, key)) { return proof.batch.entries[i].nonexist; } } } - return NonExistenceProof.nil(); + return Ics23NonExistenceProof.nil(); } - function isLeft(ExistenceProof.Data memory left, bytes memory key) private pure returns(bool) { - // ExistenceProof.isNil does not work - return ExistenceProof._empty(left) || Ops.compare(left.key, key) < 0; + function isLeft(Ics23ExistenceProof.Data memory left, bytes memory key) private pure returns(bool) { + // Ics23ExistenceProof.isNil does not work + return Ics23ExistenceProof._empty(left) || Ops.compare(left.key, key) < 0; } - function isRight(ExistenceProof.Data memory right, bytes memory key) private pure returns(bool) { - // ExistenceProof.isNil does not work - return ExistenceProof._empty(right) || Ops.compare(right.key, key) > 0; + function isRight(Ics23ExistenceProof.Data memory right, bytes memory key) private pure returns(bool) { + // Ics23ExistenceProof.isNil does not work + return Ics23ExistenceProof._empty(right) || Ops.compare(right.key, key) > 0; } } diff --git a/sol/contracts/ics23Compress.sol b/sol/contracts/ics23Compress.sol index ec4d43be..28685ee2 100644 --- a/sol/contracts/ics23Compress.sol +++ b/sol/contracts/ics23Compress.sol @@ -1,31 +1,34 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {InnerOp, ExistenceProof, NonExistenceProof, CommitmentProof, CompressedBatchEntry, CompressedBatchProof, CompressedExistenceProof, BatchEntry, BatchProof} from "./proofs.sol"; +import { + Ics23InnerOp, Ics23ExistenceProof, Ics23NonExistenceProof, Ics23CommitmentProof, Ics23CompressedBatchEntry, Ics23CompressedBatchProof, + Ics23CompressedExistenceProof, Ics23BatchEntry, Ics23BatchProof +} from "./proofs.sol"; import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; library Compress { /** - @notice will return a BatchProof if the input is CompressedBatchProof. Otherwise it will return the input. + @notice will return a Ics23BatchProof if the input is CompressedBatchProof. Otherwise it will return the input. This is safe to call multiple times (idempotent) */ - function decompress(CommitmentProof.Data memory proof) internal pure returns(CommitmentProof.Data memory) { - //CompressedBatchProof.isNil() does not work - if (CompressedBatchProof._empty(proof.compressed) == true){ + function decompress(Ics23CommitmentProof.Data memory proof) internal pure returns(Ics23CommitmentProof.Data memory) { + //Ics23CompressedBatchProof.isNil() does not work + if (Ics23CompressedBatchProof._empty(proof.compressed) == true){ return proof; } - return CommitmentProof.Data({ - exist: ExistenceProof.nil(), - nonexist: NonExistenceProof.nil(), - batch: BatchProof.Data({ + return Ics23CommitmentProof.Data({ + exist: Ics23ExistenceProof.nil(), + nonexist: Ics23NonExistenceProof.nil(), + batch: Ics23BatchProof.Data({ entries: decompress(proof.compressed) }), - compressed: CompressedBatchProof.nil() + compressed: Ics23CompressedBatchProof.nil() }); } - function decompress(CompressedBatchProof.Data memory proof) private pure returns(BatchEntry.Data[] memory) { - BatchEntry.Data[] memory entries = new BatchEntry.Data[](proof.entries.length); + function decompress(Ics23CompressedBatchProof.Data memory proof) private pure returns(Ics23BatchEntry.Data[] memory) { + Ics23BatchEntry.Data[] memory entries = new Ics23BatchEntry.Data[](proof.entries.length); for(uint i = 0; i < proof.entries.length; i++) { entries[i] = decompressEntry(proof.entries[i], proof.lookup_inners); } @@ -33,19 +36,19 @@ library Compress { } function decompressEntry( - CompressedBatchEntry.Data memory entry, - InnerOp.Data[] memory lookup - ) private pure returns(BatchEntry.Data memory) { - //CompressedExistenceProof.isNil does not work - if (CompressedExistenceProof._empty(entry.exist) == false) { - return BatchEntry.Data({ + Ics23CompressedBatchEntry.Data memory entry, + Ics23InnerOp.Data[] memory lookup + ) private pure returns(Ics23BatchEntry.Data memory) { + //Ics23CompressedExistenceProof.isNil does not work + if (Ics23CompressedExistenceProof._empty(entry.exist) == false) { + return Ics23BatchEntry.Data({ exist: decompressExist(entry.exist, lookup), - nonexist: NonExistenceProof.nil() + nonexist: Ics23NonExistenceProof.nil() }); } - return BatchEntry.Data({ - exist: ExistenceProof.nil(), - nonexist: NonExistenceProof.Data({ + return Ics23BatchEntry.Data({ + exist: Ics23ExistenceProof.nil(), + nonexist: Ics23NonExistenceProof.Data({ key: entry.nonexist.key, left: decompressExist(entry.nonexist.left, lookup), right: decompressExist(entry.nonexist.right, lookup) @@ -54,17 +57,17 @@ library Compress { } function decompressExist( - CompressedExistenceProof.Data memory proof, - InnerOp.Data[] memory lookup - ) private pure returns(ExistenceProof.Data memory) { - if (CompressedExistenceProof._empty(proof)) { - return ExistenceProof.nil(); + Ics23CompressedExistenceProof.Data memory proof, + Ics23InnerOp.Data[] memory lookup + ) private pure returns(Ics23ExistenceProof.Data memory) { + if (Ics23CompressedExistenceProof._empty(proof)) { + return Ics23ExistenceProof.nil(); } - ExistenceProof.Data memory decoProof = ExistenceProof.Data({ + Ics23ExistenceProof.Data memory decoProof = Ics23ExistenceProof.Data({ key: proof.key, value: proof.value, leaf: proof.leaf, - path : new InnerOp.Data[](proof.path.length) + path : new Ics23InnerOp.Data[](proof.path.length) }); for (uint i = 0; i < proof.path.length; i++) { require(proof.path[i] >= 0); // dev: proof.path < 0 diff --git a/sol/contracts/ics23CompressMock.sol b/sol/contracts/ics23CompressMock.sol index f8a6bde9..6098137d 100644 --- a/sol/contracts/ics23CompressMock.sol +++ b/sol/contracts/ics23CompressMock.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {CommitmentProof} from "./proofs.sol"; +import {Ics23CommitmentProof} from "./proofs.sol"; import {Compress} from "./ics23Compress.sol"; contract CompressMock { - function decompress(CommitmentProof.Data memory proof) public pure returns(CommitmentProof.Data memory) { + function decompress(Ics23CommitmentProof.Data memory proof) public pure returns(Ics23CommitmentProof.Data memory) { return Compress.decompress(proof); } } diff --git a/sol/contracts/ics23Mock.sol b/sol/contracts/ics23Mock.sol index 92c7f1af..48f2ffe7 100644 --- a/sol/contracts/ics23Mock.sol +++ b/sol/contracts/ics23Mock.sol @@ -1,16 +1,29 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {BatchProof, CompressedBatchProof, CommitmentProof, ProofSpec, ExistenceProof, NonExistenceProof} from "./proofs.sol"; +import { + Ics23BatchProof, Ics23CompressedBatchProof, Ics23CommitmentProof, Ics23ProofSpec, Ics23ExistenceProof, Ics23NonExistenceProof +} from "./proofs.sol"; import {Ics23} from "./ics23.sol"; contract ICS23Mock { - function verifyMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key, bytes memory value) public pure { + function verifyMembership( + Ics23ProofSpec.Data memory spec, + bytes memory commitmentRoot, + Ics23CommitmentProof.Data memory proof, + bytes memory key, + bytes memory value + ) public pure { Ics23.VerifyMembershipError vCode = Ics23.verifyMembership(spec, commitmentRoot, proof, key, value); require(vCode == Ics23.VerifyMembershipError.None); } - function verifyNonMembership(ProofSpec.Data memory spec, bytes memory commitmentRoot, CommitmentProof.Data memory proof, bytes memory key) public pure { + function verifyNonMembership( + Ics23ProofSpec.Data memory spec, + bytes memory commitmentRoot, + Ics23CommitmentProof.Data memory proof, + bytes memory key + ) public pure { Ics23.VerifyNonMembershipError vCode = Ics23.verifyNonMembership(spec, commitmentRoot, proof, key); require(vCode == Ics23.VerifyNonMembershipError.None); } diff --git a/sol/contracts/ics23Ops.sol b/sol/contracts/ics23Ops.sol index 801e8565..ab2f1599 100644 --- a/sol/contracts/ics23Ops.sol +++ b/sol/contracts/ics23Ops.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {LeafOp, InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, ProofSpec} from "./proofs.sol"; +import {Ics23LeafOp, Ics23InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, Ics23ProofSpec} from "./proofs.sol"; import {ProtoBufRuntime} from "./ProtoBufRuntime.sol"; import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; import {Math} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/Math.sol"; @@ -22,7 +22,7 @@ library Ops { @return VerifyExistenceError enum giving indication of where error happened, None if verification succeded */ function applyOp( - LeafOp.Data memory leafOp, + Ics23LeafOp.Data memory leafOp, bytes memory key, bytes memory value ) internal pure returns(bytes memory, ApplyLeafOpError) { @@ -69,9 +69,12 @@ library Ops { MaxPrefixLength } /** - @notice will verify the LeafOp is in the format defined in spec + @notice will verify the Ics23LeafOp is in the format defined in spec */ - function checkAgainstSpec(LeafOp.Data memory leafOp, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { + function checkAgainstSpec( + Ics23LeafOp.Data memory leafOp, + Ics23ProofSpec.Data memory spec + ) internal pure returns(CheckAgainstSpecError) { //require (leafOp.hash == spec.leaf_spec.hash); // dev: checkAgainstSpec for LeafOp - Unexpected HashOp if (leafOp.hash != spec.leaf_spec.hash) return CheckAgainstSpecError.Hash; //require(leafOp.prehash_key == spec.leaf_spec.prehash_key); // dev: checkAgainstSpec for LeafOp - Unexpected PrehashKey @@ -95,7 +98,7 @@ library Ops { /** @notice apply will calculate the hash of the next step, given the hash of the previous step */ - function applyOp(InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory, ApplyInnerOpError) { + function applyOp(Ics23InnerOp.Data memory innerOp, bytes memory child ) internal pure returns(bytes memory, ApplyInnerOpError) { //require(child.length > 0); // dev: Inner op needs child value if (child.length == 0) return (empty, ApplyInnerOpError.ChildLength); bytes memory preImage = abi.encodePacked(innerOp.prefix, child, innerOp.suffix); @@ -106,9 +109,12 @@ library Ops { } /** - @notice will verify the InnerOp is in the format defined in spec + @notice will verify the Ics23InnerOp is in the format defined in spec */ - function checkAgainstSpec(InnerOp.Data memory innerOp, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { + function checkAgainstSpec( + Ics23InnerOp.Data memory innerOp, + Ics23ProofSpec.Data memory spec + ) internal pure returns(CheckAgainstSpecError) { //require(innerOp.hash == spec.inner_spec.hash); // dev: checkAgainstSpec for InnerOp - Unexpected HashOp if (innerOp.hash != spec.inner_spec.hash) return CheckAgainstSpecError.Hash; uint256 minPrefixLength = SafeCast.toUint256(spec.inner_spec.min_prefix_length); diff --git a/sol/contracts/ics23OpsMock.sol b/sol/contracts/ics23OpsMock.sol index cf95859d..ba9afcbd 100644 --- a/sol/contracts/ics23OpsMock.sol +++ b/sol/contracts/ics23OpsMock.sol @@ -2,25 +2,25 @@ pragma solidity ^0.8.2; import {Ops} from "./ics23Ops.sol"; -import {LeafOp, InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, ProofSpec} from "./proofs.sol"; +import {Ics23LeafOp, Ics23InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, Ics23ProofSpec} from "./proofs.sol"; contract OpsMock { - function applyLeafOp(LeafOp.Data memory leaf, bytes memory key, bytes memory value) public pure returns(bytes memory) { + function applyLeafOp(Ics23LeafOp.Data memory leaf, bytes memory key, bytes memory value) public pure returns(bytes memory) { (bytes memory res, Ops.ApplyLeafOpError aCode) = Ops.applyOp(leaf, key, value); require(aCode == Ops.ApplyLeafOpError.None); // dev: expand this require to check error code return res; } - function checkAgainstLeafOpSpec(LeafOp.Data memory op, ProofSpec.Data memory spec) public pure { + function checkAgainstLeafOpSpec(Ics23LeafOp.Data memory op, Ics23ProofSpec.Data memory spec) public pure { Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code } - function applyInnerOp(InnerOp.Data memory inner,bytes memory child) public pure returns(bytes memory) { + function applyInnerOp(Ics23InnerOp.Data memory inner,bytes memory child) public pure returns(bytes memory) { (bytes memory res, Ops.ApplyInnerOpError aCode) = Ops.applyOp(inner, child); require(aCode == Ops.ApplyInnerOpError.None); // dev: expand this require to check error code return res; } - function checkAgainstInnerOpSpec(InnerOp.Data memory op, ProofSpec.Data memory spec) public pure { + function checkAgainstInnerOpSpec(Ics23InnerOp.Data memory op, Ics23ProofSpec.Data memory spec) public pure { Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(op, spec); require(cCode == Ops.CheckAgainstSpecError.None); // dev: expand this require to check error code } diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol index badc388f..46e2f8ba 100644 --- a/sol/contracts/ics23Proof.sol +++ b/sol/contracts/ics23Proof.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.2; import { - LeafOp, CompressedBatchProof, ExistenceProof, NonExistenceProof, BatchEntry, BatchProof, ProofSpec, InnerOp, InnerSpec, CommitmentProof + Ics23LeafOp, Ics23CompressedBatchProof, Ics23ExistenceProof, Ics23NonExistenceProof, Ics23BatchEntry, Ics23BatchProof, + Ics23ProofSpec, Ics23InnerOp, Ics23InnerSpec, Ics23CommitmentProof } from "./proofs.sol"; import {Ops} from "./ics23Ops.sol"; import {SafeCast} from "OpenZeppelin/openzeppelin-contracts@4.2.0/contracts/utils/math/SafeCast.sol"; @@ -22,12 +23,12 @@ library Proof{ RootNotMatching } /** - @notice verify does all checks to ensure this proof proves this key, value -> root and matches the spec. - @return VerifyExistenceError enum giving indication of where error happened, None if verification succeded - */ + @notice verify does all checks to ensure this proof proves this key, value -> root and matches the spec. + @return VerifyExistenceError enum giving indication of where error happened, None if verification succeded + */ function verify( - ExistenceProof.Data memory proof, - ProofSpec.Data memory spec, + Ics23ExistenceProof.Data memory proof, + Ics23ProofSpec.Data memory spec, bytes memory commitmentRoot, bytes memory key, bytes memory value @@ -62,9 +63,9 @@ library Proof{ @notice calculateRoot determines the root hash that matches the given proof. You must validate the result in what you have in a header. @return CalculateRootError enum giving indication of where error happened, None if verification succeded */ - function calculateRoot(ExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { - //require(LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp - if (LeafOp.isNil(proof.leaf)) return (empty, CalculateRootError.LeafNil); + function calculateRoot(Ics23ExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { + //require(Ics23LeafOp.isNil(proof.leaf) == false); // dev: Existence Proof needs defined Ics23LeafOp + if (Ics23LeafOp.isNil(proof.leaf)) return (empty, CalculateRootError.LeafNil); (bytes memory root, Ops.ApplyLeafOpError lCode) = Ops.applyOp(proof.leaf, proof.key, proof.value); if (lCode != Ops.ApplyLeafOpError.None) return (empty, CalculateRootError.LeafOp); for (uint i = 0; i < proof.path.length; i++) { @@ -87,10 +88,13 @@ library Proof{ @notice checkAgainstSpec will verify the leaf and all path steps are in the format defined in spec @return CheckAgainstSpecError enum giving indication of where error happened, None if verification succeded */ - function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) internal pure returns(CheckAgainstSpecError) { - // LeafOp.isNil does not work - //require(LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined LeafOp - if (LeafOp._empty(proof.leaf)) return CheckAgainstSpecError.EmptyLeaf; + function checkAgainstSpec( + Ics23ExistenceProof.Data memory proof, + Ics23ProofSpec.Data memory spec + ) internal pure returns(CheckAgainstSpecError) { + // Ics23LeafOp.isNil does not work + //require(Ics23LeafOp._empty(proof.leaf) == false); // dev: Existence Proof needs defined Ics23LeafOp + if (Ics23LeafOp._empty(proof.leaf)) return CheckAgainstSpecError.EmptyLeaf; Ops.CheckAgainstSpecError cCode = Ops.checkAgainstSpec(proof.leaf, spec); if (cCode != Ops.CheckAgainstSpecError.None) return CheckAgainstSpecError.OpsCheckAgainstSpec; if (spec.min_depth > 0) { @@ -126,21 +130,21 @@ library Proof{ @return VerifyNonExistenceError enum giving indication of where error happened, None if verification succeded */ function verify( - NonExistenceProof.Data memory proof, - ProofSpec.Data memory spec, + Ics23NonExistenceProof.Data memory proof, + Ics23ProofSpec.Data memory spec, bytes memory commitmentRoot, bytes memory key ) internal pure returns(VerifyNonExistenceError) { bytes memory leftKey; bytes memory rightKey; - // ExistenceProof.isNil does not work - if (ExistenceProof._empty(proof.left) == false) { + // Ics23ExistenceProof.isNil does not work + if (Ics23ExistenceProof._empty(proof.left) == false) { VerifyExistenceError eCode = verify(proof.left, spec, commitmentRoot, proof.left.key, proof.left.value); if (eCode != VerifyExistenceError.None) return VerifyNonExistenceError.VerifyLeft; leftKey = proof.left.key; } - if (ExistenceProof._empty(proof.right) == false) { + if (Ics23ExistenceProof._empty(proof.right) == false) { VerifyExistenceError eCode = verify(proof.right, spec, commitmentRoot, proof.right.key, proof.right.value); if (eCode != VerifyExistenceError.None) return VerifyNonExistenceError.VerifyRight; @@ -174,14 +178,14 @@ library Proof{ } /** - @notice calculateRoot determines the root hash that matches the given proof. You must validate the result in what you have in a header. - @return CalculateRootError enum giving indication of where error happened, None if verification succeded - */ - function calculateRoot(NonExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { - if (ExistenceProof._empty(proof.left) == false) { + @notice calculateRoot determines the root hash that matches the given proof. You must validate the result in what you have in a header. + @return CalculateRootError enum giving indication of where error happened, None if verification succeded + */ + function calculateRoot(Ics23NonExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { + if (Ics23ExistenceProof._empty(proof.left) == false) { return calculateRoot(proof.left); } - if (ExistenceProof._empty(proof.right) == false) { + if (Ics23ExistenceProof._empty(proof.right) == false) { return calculateRoot(proof.right); } //revert(); // dev: Nonexistence proof has empty Left and Right proof @@ -194,26 +198,26 @@ library Proof{ commit to the same root. This can be done with the Verify method @return CalculateRootError enum giving indication of where error happened, None if verification succeded */ - function calculateRoot(CommitmentProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { - if (ExistenceProof._empty(proof.exist) == false) { + function calculateRoot(Ics23CommitmentProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { + if (Ics23ExistenceProof._empty(proof.exist) == false) { return calculateRoot(proof.exist); } - if (NonExistenceProof._empty(proof.nonexist) == false) { + if (Ics23NonExistenceProof._empty(proof.nonexist) == false) { return calculateRoot(proof.nonexist); } - if (BatchProof._empty(proof.batch) == false) { + if (Ics23BatchProof._empty(proof.batch) == false) { //require(proof.batch.entries.length > 0); // dev: batch proof has no entry if (proof.batch.entries.length == 0) return (empty, CalculateRootError.BatchEntriesLength); - //require(BatchEntry._empty(proof.batch.entries[0]) == false); // dev: batch proof has empty entry - if (BatchEntry._empty(proof.batch.entries[0])) return (empty, CalculateRootError.BatchEntryEmpty); - if (ExistenceProof._empty(proof.batch.entries[0].exist) == false) { + //require(Ics23BatchEntry._empty(proof.batch.entries[0]) == false); // dev: batch proof has empty entry + if (Ics23BatchEntry._empty(proof.batch.entries[0])) return (empty, CalculateRootError.BatchEntryEmpty); + if (Ics23ExistenceProof._empty(proof.batch.entries[0].exist) == false) { return calculateRoot(proof.batch.entries[0].exist); } - if (NonExistenceProof._empty(proof.batch.entries[0].nonexist) == false) { + if (Ics23NonExistenceProof._empty(proof.batch.entries[0].nonexist) == false) { return calculateRoot(proof.batch.entries[0].nonexist); } } - if (CompressedBatchProof._empty(proof.compressed) == false) { + if (Ics23CompressedBatchProof._empty(proof.compressed) == false) { return calculateRoot(Compress.decompress(proof)); } //revert(); // dev: calculateRoot(CommitmentProof) empty proof @@ -222,9 +226,9 @@ library Proof{ /** - @return true if this is the left-most path in the tree - */ - function isLeftMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool) { + @return true if this is the left-most path in the tree + */ + function isLeftMost(Ics23InnerSpec.Data memory spec, Ics23InnerOp.Data[] memory path) private pure returns(bool) { (uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError gCode) = getPadding(spec, 0); if (gCode != GetPaddingError.None) return false; for (uint i = 0; i < path.length; i++) { @@ -236,9 +240,9 @@ library Proof{ } /** - @return true if this is the right-most path in the tree - */ - function isRightMost(InnerSpec.Data memory spec, InnerOp.Data[] memory path) private pure returns(bool){ + @return true if this is the right-most path in the tree + */ + function isRightMost(Ics23InnerSpec.Data memory spec, Ics23InnerOp.Data[] memory path) private pure returns(bool){ uint last = spec.child_order.length - 1; (uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError gCode) = getPadding(spec, last); if (gCode != GetPaddingError.None) return false; @@ -254,7 +258,11 @@ library Proof{ /** @notice assumes left and right have common parents checks if left is exactly one slot to the left of right */ - function isLeftStep(InnerSpec.Data memory spec, InnerOp.Data memory left, InnerOp.Data memory right) private pure returns(bool){ + function isLeftStep( + Ics23InnerSpec.Data memory spec, + Ics23InnerOp.Data memory left, + Ics23InnerOp.Data memory right + ) private pure returns(bool){ (uint leftIdx, OrderFromPaddingError lCode) = orderFromPadding(spec, left); if (lCode != OrderFromPaddingError.None) return false; (uint rightIdx, OrderFromPaddingError rCode) = orderFromPadding(spec, right); @@ -265,24 +273,24 @@ library Proof{ } /** - @notice find the common suffix from the Left.Path and Right.Path and remove it. We have LPath and RPath now, which must be neighbors. - Validate that LPath[len-1] is the left neighbor of RPath[len-1] - For step in LPath[0..len-1], validate step is right-most node - For step in RPath[0..len-1], validate step is left-most node + @notice find the common suffix from the Left.Path and Right.Path and remove it. We have LPath and RPath now, which must be neighbors. + Validate that LPath[len-1] is the left neighbor of RPath[len-1] + For step in LPath[0..len-1], validate step is right-most node + For step in RPath[0..len-1], validate step is left-most node */ function isLeftNeighbor( - InnerSpec.Data memory spec, - InnerOp.Data[] memory left, - InnerOp.Data[] memory right - ) private pure returns(bool) { + Ics23InnerSpec.Data memory spec, + Ics23InnerOp.Data[] memory left, + Ics23InnerOp.Data[] memory right + ) private pure returns(bool) { uint leftIdx = left.length - 1; uint rightIdx = right.length - 1; while (leftIdx >= 0 && rightIdx >= 0) { if (BytesLib.equal(left[leftIdx].prefix, right[rightIdx].prefix) && - BytesLib.equal(left[leftIdx].suffix, right[rightIdx].suffix)) { + BytesLib.equal(left[leftIdx].suffix, right[rightIdx].suffix)) { leftIdx -= 1; - rightIdx -= 1; - continue; + rightIdx -= 1; + continue; } break; } @@ -307,7 +315,10 @@ library Proof{ /** @notice this will look at the proof and determine which order it is... So we can see if it is branch 0, 1, 2 etc... to determine neighbors */ - function orderFromPadding(InnerSpec.Data memory spec, InnerOp.Data memory op) private pure returns(uint, OrderFromPaddingError) { + function orderFromPadding( + Ics23InnerSpec.Data memory spec, + Ics23InnerOp.Data memory op + ) private pure returns(uint, OrderFromPaddingError) { uint256 maxBranch = spec.child_order.length; for(uint branch = 0; branch < maxBranch; branch++) { (uint minp, uint maxp, uint suffix, GetPaddingError gCode) = getPadding(spec, branch); @@ -326,7 +337,7 @@ library Proof{ @notice determines prefix and suffix with the given spec and position in the tree */ function getPadding( - InnerSpec.Data memory spec, + Ics23InnerSpec.Data memory spec, uint branch ) private pure returns(uint minPrefix, uint maxPrefix, uint suffix, GetPaddingError) { uint uChildSize = SafeCast.toUint256(spec.child_size); @@ -359,7 +370,7 @@ library Proof{ return (0, GetPositionError.NoFound); } - function hasPadding(InnerOp.Data memory op, uint minPrefix, uint maxPrefix, uint suffix) private pure returns(bool) { + function hasPadding(Ics23InnerOp.Data memory op, uint minPrefix, uint maxPrefix, uint suffix) private pure returns(bool) { if (op.prefix.length < minPrefix) return false; if (op.prefix.length > maxPrefix) return false; return op.suffix.length == suffix; @@ -368,8 +379,8 @@ library Proof{ /** @return a slice of of InnerOp.Data, array[start..end] */ - function sliceInnerOps(InnerOp.Data[] memory array, uint start, uint end) private pure returns(InnerOp.Data[] memory) { - InnerOp.Data[] memory slice = new InnerOp.Data[](end-start); + function sliceInnerOps(Ics23InnerOp.Data[] memory array, uint start, uint end) private pure returns(Ics23InnerOp.Data[] memory) { + Ics23InnerOp.Data[] memory slice = new Ics23InnerOp.Data[](end-start); for (uint i = start; i < end; i++) { slice[i] = array[i]; } diff --git a/sol/contracts/ics23ProofMock.sol b/sol/contracts/ics23ProofMock.sol index 64178bf3..3c9e3bc0 100644 --- a/sol/contracts/ics23ProofMock.sol +++ b/sol/contracts/ics23ProofMock.sol @@ -1,25 +1,25 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; import {Proof} from "./ics23Proof.sol"; -import { ExistenceProof, ProofSpec, CommitmentProof} from "./proofs.sol"; +import {Ics23ExistenceProof, Ics23ProofSpec, Ics23CommitmentProof} from "./proofs.sol"; contract ProofMock { - function calculateExistenceProofRoot(ExistenceProof.Data memory proof) public pure returns(bytes memory) { + function calculateExistenceProofRoot(Ics23ExistenceProof.Data memory proof) public pure returns(bytes memory) { (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code return res; } - function checkAgainstSpec(ExistenceProof.Data memory proof, ProofSpec.Data memory spec) public pure { + function checkAgainstSpec(Ics23ExistenceProof.Data memory proof, Ics23ProofSpec.Data memory spec) public pure { Proof.CheckAgainstSpecError cCode = Proof.checkAgainstSpec(proof, spec); require(cCode == Proof.CheckAgainstSpecError.None); // dev: expand this require to check error code } - function calculateCommitmentProofRoot(CommitmentProof.Data memory proof) public pure returns(bytes memory) { + function calculateCommitmentProofRoot(Ics23CommitmentProof.Data memory proof) public pure returns(bytes memory) { (bytes memory res, Proof.CalculateRootError eCode) = Proof.calculateRoot(proof); require(eCode == Proof.CalculateRootError.None); // dev: expand this require to check error code return res; } - function protobufDecodeCommitmentProof(bytes memory protoMsg) public pure returns(CommitmentProof.Data memory) { - CommitmentProof.Data memory res = CommitmentProof.decode(protoMsg); + function protobufDecodeCommitmentProof(bytes memory protoMsg) public pure returns(Ics23CommitmentProof.Data memory) { + Ics23CommitmentProof.Data memory res = Ics23CommitmentProof.decode(protoMsg); return res; } } diff --git a/sol/contracts/proofs.sol b/sol/contracts/proofs.sol index 1ab141c5..c474e92b 100644 --- a/sol/contracts/proofs.sol +++ b/sol/contracts/proofs.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.2; +pragma solidity ^0.8.10; import "./ProtoBufRuntime.sol"; import "./GoogleProtobufAny.sol"; -library ExistenceProof { +library Ics23ExistenceProof { //struct definition struct Data { bytes key; bytes value; - LeafOp.Data leaf; - InnerOp.Data[] path; + Ics23LeafOp.Data leaf; + Ics23InnerOp.Data[] path; } // Decoder section @@ -61,81 +61,36 @@ library ExistenceProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_key(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_value(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, r); + } else + if (fieldId == 4) { + pointer += _read_unpacked_repeated_path(pointer, bs, nil(), counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } pointer = offset; - r.path = new InnerOp.Data[](counters[4]); + if (counters[4] > 0) { + require(r.path.length == 0); + r.path = new Ics23InnerOp.Data[](counters[4]); + } while (pointer < offset + sz) { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, nil(), counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, nil(), counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + if (fieldId == 4) { + pointer += _read_unpacked_repeated_path(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } return (r, sz); @@ -148,25 +103,15 @@ library ExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_key( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } + r.key = x; return sz; } @@ -175,25 +120,15 @@ library ExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_value( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.value = x; - if (counters[2] > 0) counters[2] -= 1; - } + r.value = x; return sz; } @@ -202,25 +137,15 @@ library ExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_leaf( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.leaf = x; - if (counters[3] > 0) counters[3] -= 1; - } + (Ics23LeafOp.Data memory x, uint256 sz) = _decode_Ics23LeafOp(p, bs); + r.leaf = x; return sz; } @@ -232,7 +157,7 @@ library ExistenceProof { * @param counters The counters for repeated fields * @return The number of bytes decoded */ - function _read_path( + function _read_unpacked_repeated_path( uint256 p, bytes memory bs, Data memory r, @@ -241,12 +166,12 @@ library ExistenceProof { /** * if `r` is NULL, then only counting the number of fields. */ - (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); + (Ics23InnerOp.Data memory x, uint256 sz) = _decode_Ics23InnerOp(p, bs); if (isNil(r)) { counters[4] += 1; } else { r.path[r.path.length - counters[4]] = x; - if (counters[4] > 0) counters[4] -= 1; + counters[4] -= 1; } return sz; } @@ -259,15 +184,15 @@ library ExistenceProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_LeafOp(uint256 p, bytes memory bs) + function _decode_Ics23LeafOp(uint256 p, bytes memory bs) internal pure - returns (LeafOp.Data memory, uint) + returns (Ics23LeafOp.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + (Ics23LeafOp.Data memory r, ) = Ics23LeafOp._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -278,15 +203,15 @@ library ExistenceProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_InnerOp(uint256 p, bytes memory bs) + function _decode_Ics23InnerOp(uint256 p, bytes memory bs) internal pure - returns (InnerOp.Data memory, uint) + returns (Ics23InnerOp.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); + (Ics23InnerOp.Data memory r, ) = Ics23InnerOp._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -348,7 +273,7 @@ library ExistenceProof { pointer, bs ); - pointer += LeafOp._encode_nested(r.leaf, pointer, bs); + pointer += Ics23LeafOp._encode_nested(r.leaf, pointer, bs); if (r.path.length != 0) { for(i = 0; i < r.path.length; i++) { @@ -358,7 +283,7 @@ library ExistenceProof { pointer, bs) ; - pointer += InnerOp._encode_nested(r.path[i], pointer, bs); + pointer += Ics23InnerOp._encode_nested(r.path[i], pointer, bs); } } return pointer - offset; @@ -406,9 +331,9 @@ library ExistenceProof { uint256 e;uint256 i; e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); - e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23LeafOp._estimate(r.leaf)); for(i = 0; i < r.path.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.path[i])); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23InnerOp._estimate(r.path[i])); } return e; } @@ -443,7 +368,7 @@ library ExistenceProof { function store(Data memory input, Data storage output) internal { output.key = input.key; output.value = input.value; - LeafOp.store(input.leaf, output.leaf); + Ics23LeafOp.store(input.leaf, output.leaf); for(uint256 i4 = 0; i4 < input.path.length; i4++) { output.path.push(input.path[i4]); @@ -459,11 +384,11 @@ library ExistenceProof { * @param self The in-memory struct * @param value The value to add */ - function addPath(Data memory self, InnerOp.Data memory value) internal pure { + function addPath(Data memory self, Ics23InnerOp.Data memory value) internal pure { /** * First resize the array. Then add the new element to the end. */ - InnerOp.Data[] memory tmp = new InnerOp.Data[](self.path.length + 1); + Ics23InnerOp.Data[] memory tmp = new Ics23InnerOp.Data[](self.path.length + 1); for (uint256 i = 0; i < self.path.length; i++) { tmp[i] = self.path[i]; } @@ -494,16 +419,16 @@ library ExistenceProof { } } } -//library ExistenceProof +//library Ics23ExistenceProof -library NonExistenceProof { +library Ics23NonExistenceProof { //struct definition struct Data { bytes key; - ExistenceProof.Data left; - ExistenceProof.Data right; + Ics23ExistenceProof.Data left; + Ics23ExistenceProof.Data right; } // Decoder section @@ -543,7 +468,6 @@ library NonExistenceProof { returns (Data memory, uint) { Data memory r; - uint[4] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -553,36 +477,16 @@ library NonExistenceProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_left(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_right(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_key(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_left(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_right(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -596,25 +500,15 @@ library NonExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_key( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } + r.key = x; return sz; } @@ -623,25 +517,15 @@ library NonExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_left( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.left = x; - if (counters[2] > 0) counters[2] -= 1; - } + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.left = x; return sz; } @@ -650,25 +534,15 @@ library NonExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_right( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.right = x; - if (counters[3] > 0) counters[3] -= 1; - } + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.right = x; return sz; } @@ -680,15 +554,15 @@ library NonExistenceProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_ExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23ExistenceProof(uint256 p, bytes memory bs) internal pure - returns (ExistenceProof.Data memory, uint) + returns (Ics23ExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + (Ics23ExistenceProof.Data memory r, ) = Ics23ExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -741,7 +615,7 @@ library NonExistenceProof { pointer, bs ); - pointer += ExistenceProof._encode_nested(r.left, pointer, bs); + pointer += Ics23ExistenceProof._encode_nested(r.left, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -750,7 +624,7 @@ library NonExistenceProof { pointer, bs ); - pointer += ExistenceProof._encode_nested(r.right, pointer, bs); + pointer += Ics23ExistenceProof._encode_nested(r.right, pointer, bs); return pointer - offset; } @@ -796,8 +670,8 @@ library NonExistenceProof { ) internal pure returns (uint) { uint256 e; e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.left)); - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.right)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23ExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23ExistenceProof._estimate(r.right)); return e; } // empty checker @@ -822,8 +696,8 @@ library NonExistenceProof { */ function store(Data memory input, Data storage output) internal { output.key = input.key; - ExistenceProof.store(input.left, output.left); - ExistenceProof.store(input.right, output.right); + Ics23ExistenceProof.store(input.left, output.left); + Ics23ExistenceProof.store(input.right, output.right); } @@ -851,17 +725,17 @@ library NonExistenceProof { } } } -//library NonExistenceProof +//library Ics23NonExistenceProof -library CommitmentProof { +library Ics23CommitmentProof { //struct definition struct Data { - ExistenceProof.Data exist; - NonExistenceProof.Data nonexist; - BatchProof.Data batch; - CompressedBatchProof.Data compressed; + Ics23ExistenceProof.Data exist; + Ics23NonExistenceProof.Data nonexist; + Ics23BatchProof.Data batch; + Ics23CompressedBatchProof.Data compressed; } // Decoder section @@ -901,7 +775,6 @@ library CommitmentProof { returns (Data memory, uint) { Data memory r; - uint[5] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -911,39 +784,19 @@ library CommitmentProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_exist(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_nonexist(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_batch(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_compressed(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_exist(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_batch(pointer, bs, r); + } else + if (fieldId == 4) { + pointer += _read_compressed(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -957,25 +810,15 @@ library CommitmentProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_exist( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.exist = x; - if (counters[1] > 0) counters[1] -= 1; - } + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.exist = x; return sz; } @@ -984,25 +827,15 @@ library CommitmentProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_nonexist( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.nonexist = x; - if (counters[2] > 0) counters[2] -= 1; - } + (Ics23NonExistenceProof.Data memory x, uint256 sz) = _decode_Ics23NonExistenceProof(p, bs); + r.nonexist = x; return sz; } @@ -1011,25 +844,15 @@ library CommitmentProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_batch( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (BatchProof.Data memory x, uint256 sz) = _decode_BatchProof(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.batch = x; - if (counters[3] > 0) counters[3] -= 1; - } + (Ics23BatchProof.Data memory x, uint256 sz) = _decode_Ics23BatchProof(p, bs); + r.batch = x; return sz; } @@ -1038,25 +861,15 @@ library CommitmentProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_compressed( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedBatchProof.Data memory x, uint256 sz) = _decode_CompressedBatchProof(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.compressed = x; - if (counters[4] > 0) counters[4] -= 1; - } + (Ics23CompressedBatchProof.Data memory x, uint256 sz) = _decode_Ics23CompressedBatchProof(p, bs); + r.compressed = x; return sz; } @@ -1068,15 +881,15 @@ library CommitmentProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_ExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23ExistenceProof(uint256 p, bytes memory bs) internal pure - returns (ExistenceProof.Data memory, uint) + returns (Ics23ExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + (Ics23ExistenceProof.Data memory r, ) = Ics23ExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -1087,15 +900,15 @@ library CommitmentProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_NonExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23NonExistenceProof(uint256 p, bytes memory bs) internal pure - returns (NonExistenceProof.Data memory, uint) + returns (Ics23NonExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); + (Ics23NonExistenceProof.Data memory r, ) = Ics23NonExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -1106,15 +919,15 @@ library CommitmentProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_BatchProof(uint256 p, bytes memory bs) + function _decode_Ics23BatchProof(uint256 p, bytes memory bs) internal pure - returns (BatchProof.Data memory, uint) + returns (Ics23BatchProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (BatchProof.Data memory r, ) = BatchProof._decode(pointer, bs, sz); + (Ics23BatchProof.Data memory r, ) = Ics23BatchProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -1125,15 +938,15 @@ library CommitmentProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_CompressedBatchProof(uint256 p, bytes memory bs) + function _decode_Ics23CompressedBatchProof(uint256 p, bytes memory bs) internal pure - returns (CompressedBatchProof.Data memory, uint) + returns (Ics23CompressedBatchProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (CompressedBatchProof.Data memory r, ) = CompressedBatchProof._decode(pointer, bs, sz); + (Ics23CompressedBatchProof.Data memory r, ) = Ics23CompressedBatchProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -1177,7 +990,7 @@ library CommitmentProof { pointer, bs ); - pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); + pointer += Ics23ExistenceProof._encode_nested(r.exist, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -1186,7 +999,7 @@ library CommitmentProof { pointer, bs ); - pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + pointer += Ics23NonExistenceProof._encode_nested(r.nonexist, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -1195,7 +1008,7 @@ library CommitmentProof { pointer, bs ); - pointer += BatchProof._encode_nested(r.batch, pointer, bs); + pointer += Ics23BatchProof._encode_nested(r.batch, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -1204,7 +1017,7 @@ library CommitmentProof { pointer, bs ); - pointer += CompressedBatchProof._encode_nested(r.compressed, pointer, bs); + pointer += Ics23CompressedBatchProof._encode_nested(r.compressed, pointer, bs); return pointer - offset; } @@ -1249,10 +1062,10 @@ library CommitmentProof { Data memory r ) internal pure returns (uint) { uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); - e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); - e += 1 + ProtoBufRuntime._sz_lendelim(BatchProof._estimate(r.batch)); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchProof._estimate(r.compressed)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23NonExistenceProof._estimate(r.nonexist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23BatchProof._estimate(r.batch)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedBatchProof._estimate(r.compressed)); return e; } // empty checker @@ -1272,10 +1085,10 @@ library CommitmentProof { * @param output The in-storage struct */ function store(Data memory input, Data storage output) internal { - ExistenceProof.store(input.exist, output.exist); - NonExistenceProof.store(input.nonexist, output.nonexist); - BatchProof.store(input.batch, output.batch); - CompressedBatchProof.store(input.compressed, output.compressed); + Ics23ExistenceProof.store(input.exist, output.exist); + Ics23NonExistenceProof.store(input.nonexist, output.nonexist); + Ics23BatchProof.store(input.batch, output.batch); + Ics23CompressedBatchProof.store(input.compressed, output.compressed); } @@ -1303,9 +1116,9 @@ library CommitmentProof { } } } -//library CommitmentProof +//library Ics23CommitmentProof -library LeafOp { +library Ics23LeafOp { //struct definition @@ -1354,7 +1167,6 @@ library LeafOp { returns (Data memory, uint) { Data memory r; - uint[6] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -1364,42 +1176,22 @@ library LeafOp { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_hash(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_prehash_key(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_prehash_value(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_length(pointer, bs, r, counters); - } - else if (fieldId == 5) { - pointer += _read_prefix(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_hash(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_prehash_key(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_prehash_value(pointer, bs, r); + } else + if (fieldId == 4) { + pointer += _read_length(pointer, bs, r); + } else + if (fieldId == 5) { + pointer += _read_prefix(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -1413,26 +1205,16 @@ library LeafOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_hash( uint256 p, bytes memory bs, - Data memory r, - uint[6] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[1] += 1; - } else { - r.hash = x; - if(counters[1] > 0) counters[1] -= 1; - } + r.hash = x; return sz; } @@ -1441,26 +1223,16 @@ library LeafOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_prehash_key( uint256 p, bytes memory bs, - Data memory r, - uint[6] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[2] += 1; - } else { - r.prehash_key = x; - if(counters[2] > 0) counters[2] -= 1; - } + r.prehash_key = x; return sz; } @@ -1469,26 +1241,16 @@ library LeafOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_prehash_value( uint256 p, bytes memory bs, - Data memory r, - uint[6] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[3] += 1; - } else { - r.prehash_value = x; - if(counters[3] > 0) counters[3] -= 1; - } + r.prehash_value = x; return sz; } @@ -1497,26 +1259,16 @@ library LeafOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_length( uint256 p, bytes memory bs, - Data memory r, - uint[6] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); PROOFS_PROTO_GLOBAL_ENUMS.LengthOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_LengthOp(tmp); - if (isNil(r)) { - counters[4] += 1; - } else { - r.length = x; - if(counters[4] > 0) counters[4] -= 1; - } + r.length = x; return sz; } @@ -1525,25 +1277,15 @@ library LeafOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_prefix( uint256 p, bytes memory bs, - Data memory r, - uint[6] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[5] += 1; - } else { - r.prefix = x; - if (counters[5] > 0) counters[5] -= 1; - } + r.prefix = x; return sz; } @@ -1748,9 +1490,9 @@ library LeafOp { } } } -//library LeafOp +//library Ics23LeafOp -library InnerOp { +library Ics23InnerOp { //struct definition @@ -1797,7 +1539,6 @@ library InnerOp { returns (Data memory, uint) { Data memory r; - uint[4] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -1807,36 +1548,16 @@ library InnerOp { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_hash(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_prefix(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_suffix(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_hash(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_prefix(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_suffix(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -1850,26 +1571,16 @@ library InnerOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_hash( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[1] += 1; - } else { - r.hash = x; - if(counters[1] > 0) counters[1] -= 1; - } + r.hash = x; return sz; } @@ -1878,25 +1589,15 @@ library InnerOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_prefix( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.prefix = x; - if (counters[2] > 0) counters[2] -= 1; - } + r.prefix = x; return sz; } @@ -1905,25 +1606,15 @@ library InnerOp { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_suffix( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.suffix = x; - if (counters[3] > 0) counters[3] -= 1; - } + r.suffix = x; return sz; } @@ -2095,15 +1786,15 @@ library InnerOp { } } } -//library InnerOp +//library Ics23InnerOp -library ProofSpec { +library Ics23ProofSpec { //struct definition struct Data { - LeafOp.Data leaf_spec; - InnerSpec.Data inner_spec; + Ics23LeafOp.Data leaf_spec; + Ics23InnerSpec.Data inner_spec; int32 max_depth; int32 min_depth; } @@ -2145,7 +1836,6 @@ library ProofSpec { returns (Data memory, uint) { Data memory r; - uint[5] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -2155,39 +1845,19 @@ library ProofSpec { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_leaf_spec(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_inner_spec(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_max_depth(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_min_depth(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_leaf_spec(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_inner_spec(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_max_depth(pointer, bs, r); + } else + if (fieldId == 4) { + pointer += _read_min_depth(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -2201,25 +1871,15 @@ library ProofSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_leaf_spec( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.leaf_spec = x; - if (counters[1] > 0) counters[1] -= 1; - } + (Ics23LeafOp.Data memory x, uint256 sz) = _decode_Ics23LeafOp(p, bs); + r.leaf_spec = x; return sz; } @@ -2228,25 +1888,15 @@ library ProofSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_inner_spec( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (InnerSpec.Data memory x, uint256 sz) = _decode_InnerSpec(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.inner_spec = x; - if (counters[2] > 0) counters[2] -= 1; - } + (Ics23InnerSpec.Data memory x, uint256 sz) = _decode_Ics23InnerSpec(p, bs); + r.inner_spec = x; return sz; } @@ -2255,25 +1905,15 @@ library ProofSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_max_depth( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.max_depth = x; - if (counters[3] > 0) counters[3] -= 1; - } + r.max_depth = x; return sz; } @@ -2282,25 +1922,15 @@ library ProofSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_min_depth( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.min_depth = x; - if (counters[4] > 0) counters[4] -= 1; - } + r.min_depth = x; return sz; } @@ -2312,15 +1942,15 @@ library ProofSpec { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_LeafOp(uint256 p, bytes memory bs) + function _decode_Ics23LeafOp(uint256 p, bytes memory bs) internal pure - returns (LeafOp.Data memory, uint) + returns (Ics23LeafOp.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + (Ics23LeafOp.Data memory r, ) = Ics23LeafOp._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -2331,15 +1961,15 @@ library ProofSpec { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_InnerSpec(uint256 p, bytes memory bs) + function _decode_Ics23InnerSpec(uint256 p, bytes memory bs) internal pure - returns (InnerSpec.Data memory, uint) + returns (Ics23InnerSpec.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (InnerSpec.Data memory r, ) = InnerSpec._decode(pointer, bs, sz); + (Ics23InnerSpec.Data memory r, ) = Ics23InnerSpec._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -2383,7 +2013,7 @@ library ProofSpec { pointer, bs ); - pointer += LeafOp._encode_nested(r.leaf_spec, pointer, bs); + pointer += Ics23LeafOp._encode_nested(r.leaf_spec, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -2392,7 +2022,7 @@ library ProofSpec { pointer, bs ); - pointer += InnerSpec._encode_nested(r.inner_spec, pointer, bs); + pointer += Ics23InnerSpec._encode_nested(r.inner_spec, pointer, bs); if (r.max_depth != 0) { pointer += ProtoBufRuntime._encode_key( @@ -2455,8 +2085,8 @@ library ProofSpec { Data memory r ) internal pure returns (uint) { uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf_spec)); - e += 1 + ProtoBufRuntime._sz_lendelim(InnerSpec._estimate(r.inner_spec)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23LeafOp._estimate(r.leaf_spec)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23InnerSpec._estimate(r.inner_spec)); e += 1 + ProtoBufRuntime._sz_int32(r.max_depth); e += 1 + ProtoBufRuntime._sz_int32(r.min_depth); return e; @@ -2486,8 +2116,8 @@ library ProofSpec { * @param output The in-storage struct */ function store(Data memory input, Data storage output) internal { - LeafOp.store(input.leaf_spec, output.leaf_spec); - InnerSpec.store(input.inner_spec, output.inner_spec); + Ics23LeafOp.store(input.leaf_spec, output.leaf_spec); + Ics23InnerSpec.store(input.inner_spec, output.inner_spec); output.max_depth = input.max_depth; output.min_depth = input.min_depth; @@ -2517,9 +2147,9 @@ library ProofSpec { } } } -//library ProofSpec +//library Ics23ProofSpec -library InnerSpec { +library Ics23InnerSpec { //struct definition @@ -2579,93 +2209,46 @@ library InnerSpec { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_child_order(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_child_size(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_min_prefix_length(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_max_prefix_length(pointer, bs, r, counters); - } - else if (fieldId == 5) { - pointer += _read_empty_child(pointer, bs, r, counters); - } - else if (fieldId == 6) { - pointer += _read_hash(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; + pointer += _read_packed_repeated_child_order(pointer, bs, r); + } else { + pointer += _read_unpacked_repeated_child_order(pointer, bs, nil(), counters); } + } else + if (fieldId == 2) { + pointer += _read_child_size(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_min_prefix_length(pointer, bs, r); + } else + if (fieldId == 4) { + pointer += _read_max_prefix_length(pointer, bs, r); + } else + if (fieldId == 5) { + pointer += _read_empty_child(pointer, bs, r); + } else + if (fieldId == 6) { + pointer += _read_hash(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } pointer = offset; - r.child_order = new int32[](counters[1]); + if (counters[1] > 0) { + require(r.child_order.length == 0); + r.child_order = new int32[](counters[1]); + } while (pointer < offset + sz) { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_child_order(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_child_size(pointer, bs, nil(), counters); - } - else if (fieldId == 3) { - pointer += _read_min_prefix_length(pointer, bs, nil(), counters); - } - else if (fieldId == 4) { - pointer += _read_max_prefix_length(pointer, bs, nil(), counters); - } - else if (fieldId == 5) { - pointer += _read_empty_child(pointer, bs, nil(), counters); - } - else if (fieldId == 6) { - pointer += _read_hash(pointer, bs, nil(), counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + if (fieldId == 1 && wireType != ProtoBufRuntime.WireType.LengthDelim) { + pointer += _read_unpacked_repeated_child_order(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } return (r, sz); @@ -2681,7 +2264,7 @@ library InnerSpec { * @param counters The counters for repeated fields * @return The number of bytes decoded */ - function _read_child_order( + function _read_unpacked_repeated_child_order( uint256 p, bytes memory bs, Data memory r, @@ -2695,7 +2278,7 @@ library InnerSpec { counters[1] += 1; } else { r.child_order[r.child_order.length - counters[1]] = x; - if (counters[1] > 0) counters[1] -= 1; + counters[1] -= 1; } return sz; } @@ -2705,25 +2288,39 @@ library InnerSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields + * @return The number of bytes decoded + */ + function _read_packed_repeated_child_order( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (uint256 len, uint256 size) = ProtoBufRuntime._decode_varint(p, bs); + p += size; + uint256 count = ProtoBufRuntime._count_packed_repeated_varint(p, len, bs); + r.child_order = new int32[](count); + for (uint256 i = 0; i < count; i++) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + p += sz; + r.child_order[i] = x; + } + return size + len; + } + + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct * @return The number of bytes decoded */ function _read_child_size( uint256 p, bytes memory bs, - Data memory r, - uint[7] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.child_size = x; - if (counters[2] > 0) counters[2] -= 1; - } + r.child_size = x; return sz; } @@ -2732,25 +2329,15 @@ library InnerSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_min_prefix_length( uint256 p, bytes memory bs, - Data memory r, - uint[7] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.min_prefix_length = x; - if (counters[3] > 0) counters[3] -= 1; - } + r.min_prefix_length = x; return sz; } @@ -2759,25 +2346,15 @@ library InnerSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_max_prefix_length( uint256 p, bytes memory bs, - Data memory r, - uint[7] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); - if (isNil(r)) { - counters[4] += 1; - } else { - r.max_prefix_length = x; - if (counters[4] > 0) counters[4] -= 1; - } + r.max_prefix_length = x; return sz; } @@ -2786,25 +2363,15 @@ library InnerSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_empty_child( uint256 p, bytes memory bs, - Data memory r, - uint[7] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[5] += 1; - } else { - r.empty_child = x; - if (counters[5] > 0) counters[5] -= 1; - } + r.empty_child = x; return sz; } @@ -2813,26 +2380,16 @@ library InnerSpec { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_hash( uint256 p, bytes memory bs, - Data memory r, - uint[7] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); - if (isNil(r)) { - counters[6] += 1; - } else { - r.hash = x; - if(counters[6] > 0) counters[6] -= 1; - } + r.hash = x; return sz; } @@ -2870,13 +2427,18 @@ library InnerSpec { uint256 pointer = p; uint256 i; if (r.child_order.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 1, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_varint( + ProtoBufRuntime._estimate_packed_repeated_int32(r.child_order), + pointer, + bs + ); for(i = 0; i < r.child_order.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 1, - ProtoBufRuntime.WireType.Varint, - pointer, - bs) - ; pointer += ProtoBufRuntime._encode_int32(r.child_order[i], pointer, bs); } } @@ -2969,9 +2531,7 @@ library InnerSpec { Data memory r ) internal pure returns (uint) { uint256 e;uint256 i; - for(i = 0; i < r.child_order.length; i++) { - e += 1 + ProtoBufRuntime._sz_int32(r.child_order[i]); - } + e += 1 + ProtoBufRuntime._sz_lendelim(ProtoBufRuntime._estimate_packed_repeated_int32(r.child_order)); e += 1 + ProtoBufRuntime._sz_int32(r.child_size); e += 1 + ProtoBufRuntime._sz_int32(r.min_prefix_length); e += 1 + ProtoBufRuntime._sz_int32(r.max_prefix_length); @@ -3071,14 +2631,14 @@ library InnerSpec { } } } -//library InnerSpec +//library Ics23InnerSpec -library BatchProof { +library Ics23BatchProof { //struct definition struct Data { - BatchEntry.Data[] entries; + Ics23BatchEntry.Data[] entries; } // Decoder section @@ -3128,63 +2688,27 @@ library BatchProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_entries(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_unpacked_repeated_entries(pointer, bs, nil(), counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } pointer = offset; - r.entries = new BatchEntry.Data[](counters[1]); + if (counters[1] > 0) { + require(r.entries.length == 0); + r.entries = new Ics23BatchEntry.Data[](counters[1]); + } while (pointer < offset + sz) { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_entries(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_unpacked_repeated_entries(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } return (r, sz); @@ -3200,7 +2724,7 @@ library BatchProof { * @param counters The counters for repeated fields * @return The number of bytes decoded */ - function _read_entries( + function _read_unpacked_repeated_entries( uint256 p, bytes memory bs, Data memory r, @@ -3209,12 +2733,12 @@ library BatchProof { /** * if `r` is NULL, then only counting the number of fields. */ - (BatchEntry.Data memory x, uint256 sz) = _decode_BatchEntry(p, bs); + (Ics23BatchEntry.Data memory x, uint256 sz) = _decode_Ics23BatchEntry(p, bs); if (isNil(r)) { counters[1] += 1; } else { r.entries[r.entries.length - counters[1]] = x; - if (counters[1] > 0) counters[1] -= 1; + counters[1] -= 1; } return sz; } @@ -3227,15 +2751,15 @@ library BatchProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_BatchEntry(uint256 p, bytes memory bs) + function _decode_Ics23BatchEntry(uint256 p, bytes memory bs) internal pure - returns (BatchEntry.Data memory, uint) + returns (Ics23BatchEntry.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (BatchEntry.Data memory r, ) = BatchEntry._decode(pointer, bs, sz); + (Ics23BatchEntry.Data memory r, ) = Ics23BatchEntry._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -3280,7 +2804,7 @@ library BatchProof { pointer, bs) ; - pointer += BatchEntry._encode_nested(r.entries[i], pointer, bs); + pointer += Ics23BatchEntry._encode_nested(r.entries[i], pointer, bs); } } return pointer - offset; @@ -3327,7 +2851,7 @@ library BatchProof { ) internal pure returns (uint) { uint256 e;uint256 i; for(i = 0; i < r.entries.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(BatchEntry._estimate(r.entries[i])); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23BatchEntry._estimate(r.entries[i])); } return e; } @@ -3367,11 +2891,11 @@ library BatchProof { * @param self The in-memory struct * @param value The value to add */ - function addEntries(Data memory self, BatchEntry.Data memory value) internal pure { + function addEntries(Data memory self, Ics23BatchEntry.Data memory value) internal pure { /** * First resize the array. Then add the new element to the end. */ - BatchEntry.Data[] memory tmp = new BatchEntry.Data[](self.entries.length + 1); + Ics23BatchEntry.Data[] memory tmp = new Ics23BatchEntry.Data[](self.entries.length + 1); for (uint256 i = 0; i < self.entries.length; i++) { tmp[i] = self.entries[i]; } @@ -3402,15 +2926,15 @@ library BatchProof { } } } -//library BatchProof +//library Ics23BatchProof -library BatchEntry { +library Ics23BatchEntry { //struct definition struct Data { - ExistenceProof.Data exist; - NonExistenceProof.Data nonexist; + Ics23ExistenceProof.Data exist; + Ics23NonExistenceProof.Data nonexist; } // Decoder section @@ -3450,7 +2974,6 @@ library BatchEntry { returns (Data memory, uint) { Data memory r; - uint[3] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -3460,33 +2983,13 @@ library BatchEntry { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_exist(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_nonexist(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_exist(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -3500,25 +3003,15 @@ library BatchEntry { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_exist( uint256 p, bytes memory bs, - Data memory r, - uint[3] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (ExistenceProof.Data memory x, uint256 sz) = _decode_ExistenceProof(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.exist = x; - if (counters[1] > 0) counters[1] -= 1; - } + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.exist = x; return sz; } @@ -3527,25 +3020,15 @@ library BatchEntry { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_nonexist( uint256 p, bytes memory bs, - Data memory r, - uint[3] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (NonExistenceProof.Data memory x, uint256 sz) = _decode_NonExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.nonexist = x; - if (counters[2] > 0) counters[2] -= 1; - } + (Ics23NonExistenceProof.Data memory x, uint256 sz) = _decode_Ics23NonExistenceProof(p, bs); + r.nonexist = x; return sz; } @@ -3557,15 +3040,15 @@ library BatchEntry { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_ExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23ExistenceProof(uint256 p, bytes memory bs) internal pure - returns (ExistenceProof.Data memory, uint) + returns (Ics23ExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (ExistenceProof.Data memory r, ) = ExistenceProof._decode(pointer, bs, sz); + (Ics23ExistenceProof.Data memory r, ) = Ics23ExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -3576,15 +3059,15 @@ library BatchEntry { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_NonExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23NonExistenceProof(uint256 p, bytes memory bs) internal pure - returns (NonExistenceProof.Data memory, uint) + returns (Ics23NonExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (NonExistenceProof.Data memory r, ) = NonExistenceProof._decode(pointer, bs, sz); + (Ics23NonExistenceProof.Data memory r, ) = Ics23NonExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -3628,7 +3111,7 @@ library BatchEntry { pointer, bs ); - pointer += ExistenceProof._encode_nested(r.exist, pointer, bs); + pointer += Ics23ExistenceProof._encode_nested(r.exist, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -3637,7 +3120,7 @@ library BatchEntry { pointer, bs ); - pointer += NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + pointer += Ics23NonExistenceProof._encode_nested(r.nonexist, pointer, bs); return pointer - offset; } @@ -3682,8 +3165,8 @@ library BatchEntry { Data memory r ) internal pure returns (uint) { uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(ExistenceProof._estimate(r.exist)); - e += 1 + ProtoBufRuntime._sz_lendelim(NonExistenceProof._estimate(r.nonexist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23NonExistenceProof._estimate(r.nonexist)); return e; } // empty checker @@ -3703,8 +3186,8 @@ library BatchEntry { * @param output The in-storage struct */ function store(Data memory input, Data storage output) internal { - ExistenceProof.store(input.exist, output.exist); - NonExistenceProof.store(input.nonexist, output.nonexist); + Ics23ExistenceProof.store(input.exist, output.exist); + Ics23NonExistenceProof.store(input.nonexist, output.nonexist); } @@ -3732,15 +3215,15 @@ library BatchEntry { } } } -//library BatchEntry +//library Ics23BatchEntry -library CompressedBatchProof { +library Ics23CompressedBatchProof { //struct definition struct Data { - CompressedBatchEntry.Data[] entries; - InnerOp.Data[] lookup_inners; + Ics23CompressedBatchEntry.Data[] entries; + Ics23InnerOp.Data[] lookup_inners; } // Decoder section @@ -3790,70 +3273,37 @@ library CompressedBatchProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_entries(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_lookup_inners(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_unpacked_repeated_entries(pointer, bs, nil(), counters); + } else + if (fieldId == 2) { + pointer += _read_unpacked_repeated_lookup_inners(pointer, bs, nil(), counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } pointer = offset; - r.entries = new CompressedBatchEntry.Data[](counters[1]); - r.lookup_inners = new InnerOp.Data[](counters[2]); + if (counters[1] > 0) { + require(r.entries.length == 0); + r.entries = new Ics23CompressedBatchEntry.Data[](counters[1]); + } + if (counters[2] > 0) { + require(r.lookup_inners.length == 0); + r.lookup_inners = new Ics23InnerOp.Data[](counters[2]); + } while (pointer < offset + sz) { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_entries(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_lookup_inners(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_unpacked_repeated_entries(pointer, bs, r, counters); + } else + if (fieldId == 2) { + pointer += _read_unpacked_repeated_lookup_inners(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } return (r, sz); @@ -3869,7 +3319,7 @@ library CompressedBatchProof { * @param counters The counters for repeated fields * @return The number of bytes decoded */ - function _read_entries( + function _read_unpacked_repeated_entries( uint256 p, bytes memory bs, Data memory r, @@ -3878,12 +3328,12 @@ library CompressedBatchProof { /** * if `r` is NULL, then only counting the number of fields. */ - (CompressedBatchEntry.Data memory x, uint256 sz) = _decode_CompressedBatchEntry(p, bs); + (Ics23CompressedBatchEntry.Data memory x, uint256 sz) = _decode_Ics23CompressedBatchEntry(p, bs); if (isNil(r)) { counters[1] += 1; } else { r.entries[r.entries.length - counters[1]] = x; - if (counters[1] > 0) counters[1] -= 1; + counters[1] -= 1; } return sz; } @@ -3896,7 +3346,7 @@ library CompressedBatchProof { * @param counters The counters for repeated fields * @return The number of bytes decoded */ - function _read_lookup_inners( + function _read_unpacked_repeated_lookup_inners( uint256 p, bytes memory bs, Data memory r, @@ -3905,12 +3355,12 @@ library CompressedBatchProof { /** * if `r` is NULL, then only counting the number of fields. */ - (InnerOp.Data memory x, uint256 sz) = _decode_InnerOp(p, bs); + (Ics23InnerOp.Data memory x, uint256 sz) = _decode_Ics23InnerOp(p, bs); if (isNil(r)) { counters[2] += 1; } else { r.lookup_inners[r.lookup_inners.length - counters[2]] = x; - if (counters[2] > 0) counters[2] -= 1; + counters[2] -= 1; } return sz; } @@ -3923,15 +3373,15 @@ library CompressedBatchProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_CompressedBatchEntry(uint256 p, bytes memory bs) + function _decode_Ics23CompressedBatchEntry(uint256 p, bytes memory bs) internal pure - returns (CompressedBatchEntry.Data memory, uint) + returns (Ics23CompressedBatchEntry.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (CompressedBatchEntry.Data memory r, ) = CompressedBatchEntry._decode(pointer, bs, sz); + (Ics23CompressedBatchEntry.Data memory r, ) = Ics23CompressedBatchEntry._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -3942,15 +3392,15 @@ library CompressedBatchProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_InnerOp(uint256 p, bytes memory bs) + function _decode_Ics23InnerOp(uint256 p, bytes memory bs) internal pure - returns (InnerOp.Data memory, uint) + returns (Ics23InnerOp.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (InnerOp.Data memory r, ) = InnerOp._decode(pointer, bs, sz); + (Ics23InnerOp.Data memory r, ) = Ics23InnerOp._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -3995,7 +3445,7 @@ library CompressedBatchProof { pointer, bs) ; - pointer += CompressedBatchEntry._encode_nested(r.entries[i], pointer, bs); + pointer += Ics23CompressedBatchEntry._encode_nested(r.entries[i], pointer, bs); } } if (r.lookup_inners.length != 0) { @@ -4006,7 +3456,7 @@ library CompressedBatchProof { pointer, bs) ; - pointer += InnerOp._encode_nested(r.lookup_inners[i], pointer, bs); + pointer += Ics23InnerOp._encode_nested(r.lookup_inners[i], pointer, bs); } } return pointer - offset; @@ -4053,10 +3503,10 @@ library CompressedBatchProof { ) internal pure returns (uint) { uint256 e;uint256 i; for(i = 0; i < r.entries.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedBatchEntry._estimate(r.entries[i])); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedBatchEntry._estimate(r.entries[i])); } for(i = 0; i < r.lookup_inners.length; i++) { - e += 1 + ProtoBufRuntime._sz_lendelim(InnerOp._estimate(r.lookup_inners[i])); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23InnerOp._estimate(r.lookup_inners[i])); } return e; } @@ -4105,11 +3555,11 @@ library CompressedBatchProof { * @param self The in-memory struct * @param value The value to add */ - function addEntries(Data memory self, CompressedBatchEntry.Data memory value) internal pure { + function addEntries(Data memory self, Ics23CompressedBatchEntry.Data memory value) internal pure { /** * First resize the array. Then add the new element to the end. */ - CompressedBatchEntry.Data[] memory tmp = new CompressedBatchEntry.Data[](self.entries.length + 1); + Ics23CompressedBatchEntry.Data[] memory tmp = new Ics23CompressedBatchEntry.Data[](self.entries.length + 1); for (uint256 i = 0; i < self.entries.length; i++) { tmp[i] = self.entries[i]; } @@ -4123,11 +3573,11 @@ library CompressedBatchProof { * @param self The in-memory struct * @param value The value to add */ - function addLookupInners(Data memory self, InnerOp.Data memory value) internal pure { + function addLookupInners(Data memory self, Ics23InnerOp.Data memory value) internal pure { /** * First resize the array. Then add the new element to the end. */ - InnerOp.Data[] memory tmp = new InnerOp.Data[](self.lookup_inners.length + 1); + Ics23InnerOp.Data[] memory tmp = new Ics23InnerOp.Data[](self.lookup_inners.length + 1); for (uint256 i = 0; i < self.lookup_inners.length; i++) { tmp[i] = self.lookup_inners[i]; } @@ -4158,15 +3608,15 @@ library CompressedBatchProof { } } } -//library CompressedBatchProof +//library Ics23CompressedBatchProof -library CompressedBatchEntry { +library Ics23CompressedBatchEntry { //struct definition struct Data { - CompressedExistenceProof.Data exist; - CompressedNonExistenceProof.Data nonexist; + Ics23CompressedExistenceProof.Data exist; + Ics23CompressedNonExistenceProof.Data nonexist; } // Decoder section @@ -4206,7 +3656,6 @@ library CompressedBatchEntry { returns (Data memory, uint) { Data memory r; - uint[3] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -4216,33 +3665,13 @@ library CompressedBatchEntry { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_exist(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_nonexist(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_exist(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -4256,25 +3685,15 @@ library CompressedBatchEntry { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_exist( uint256 p, bytes memory bs, - Data memory r, - uint[3] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.exist = x; - if (counters[1] > 0) counters[1] -= 1; - } + (Ics23CompressedExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedExistenceProof(p, bs); + r.exist = x; return sz; } @@ -4283,25 +3702,15 @@ library CompressedBatchEntry { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_nonexist( uint256 p, bytes memory bs, - Data memory r, - uint[3] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedNonExistenceProof.Data memory x, uint256 sz) = _decode_CompressedNonExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.nonexist = x; - if (counters[2] > 0) counters[2] -= 1; - } + (Ics23CompressedNonExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedNonExistenceProof(p, bs); + r.nonexist = x; return sz; } @@ -4313,15 +3722,15 @@ library CompressedBatchEntry { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23CompressedExistenceProof(uint256 p, bytes memory bs) internal pure - returns (CompressedExistenceProof.Data memory, uint) + returns (Ics23CompressedExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); + (Ics23CompressedExistenceProof.Data memory r, ) = Ics23CompressedExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -4332,15 +3741,15 @@ library CompressedBatchEntry { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_CompressedNonExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23CompressedNonExistenceProof(uint256 p, bytes memory bs) internal pure - returns (CompressedNonExistenceProof.Data memory, uint) + returns (Ics23CompressedNonExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (CompressedNonExistenceProof.Data memory r, ) = CompressedNonExistenceProof._decode(pointer, bs, sz); + (Ics23CompressedNonExistenceProof.Data memory r, ) = Ics23CompressedNonExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -4384,7 +3793,7 @@ library CompressedBatchEntry { pointer, bs ); - pointer += CompressedExistenceProof._encode_nested(r.exist, pointer, bs); + pointer += Ics23CompressedExistenceProof._encode_nested(r.exist, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -4393,7 +3802,7 @@ library CompressedBatchEntry { pointer, bs ); - pointer += CompressedNonExistenceProof._encode_nested(r.nonexist, pointer, bs); + pointer += Ics23CompressedNonExistenceProof._encode_nested(r.nonexist, pointer, bs); return pointer - offset; } @@ -4438,8 +3847,8 @@ library CompressedBatchEntry { Data memory r ) internal pure returns (uint) { uint256 e; - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.exist)); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedNonExistenceProof._estimate(r.nonexist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedNonExistenceProof._estimate(r.nonexist)); return e; } // empty checker @@ -4459,8 +3868,8 @@ library CompressedBatchEntry { * @param output The in-storage struct */ function store(Data memory input, Data storage output) internal { - CompressedExistenceProof.store(input.exist, output.exist); - CompressedNonExistenceProof.store(input.nonexist, output.nonexist); + Ics23CompressedExistenceProof.store(input.exist, output.exist); + Ics23CompressedNonExistenceProof.store(input.nonexist, output.nonexist); } @@ -4488,16 +3897,16 @@ library CompressedBatchEntry { } } } -//library CompressedBatchEntry +//library Ics23CompressedBatchEntry -library CompressedExistenceProof { +library Ics23CompressedExistenceProof { //struct definition struct Data { bytes key; bytes value; - LeafOp.Data leaf; + Ics23LeafOp.Data leaf; int32[] path; } @@ -4548,81 +3957,40 @@ library CompressedExistenceProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, r, counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, nil(), counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } + pointer += _read_key(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_value(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_leaf(pointer, bs, r); + } else + if (fieldId == 4) { if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; + pointer += _read_packed_repeated_path(pointer, bs, r); + } else { + pointer += _read_unpacked_repeated_path(pointer, bs, nil(), counters); } + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } pointer = offset; - r.path = new int32[](counters[4]); + if (counters[4] > 0) { + require(r.path.length == 0); + r.path = new int32[](counters[4]); + } while (pointer < offset + sz) { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; - if (fieldId == 1) { - pointer += _read_key(pointer, bs, nil(), counters); - } - else if (fieldId == 2) { - pointer += _read_value(pointer, bs, nil(), counters); - } - else if (fieldId == 3) { - pointer += _read_leaf(pointer, bs, nil(), counters); - } - else if (fieldId == 4) { - pointer += _read_path(pointer, bs, r, counters); - } - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + if (fieldId == 4 && wireType != ProtoBufRuntime.WireType.LengthDelim) { + pointer += _read_unpacked_repeated_path(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } return (r, sz); @@ -4635,25 +4003,15 @@ library CompressedExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_key( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } + r.key = x; return sz; } @@ -4662,25 +4020,15 @@ library CompressedExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_value( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.value = x; - if (counters[2] > 0) counters[2] -= 1; - } + r.value = x; return sz; } @@ -4689,25 +4037,15 @@ library CompressedExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_leaf( uint256 p, bytes memory bs, - Data memory r, - uint[5] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (LeafOp.Data memory x, uint256 sz) = _decode_LeafOp(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.leaf = x; - if (counters[3] > 0) counters[3] -= 1; - } + (Ics23LeafOp.Data memory x, uint256 sz) = _decode_Ics23LeafOp(p, bs); + r.leaf = x; return sz; } @@ -4719,7 +4057,7 @@ library CompressedExistenceProof { * @param counters The counters for repeated fields * @return The number of bytes decoded */ - function _read_path( + function _read_unpacked_repeated_path( uint256 p, bytes memory bs, Data memory r, @@ -4733,11 +4071,35 @@ library CompressedExistenceProof { counters[4] += 1; } else { r.path[r.path.length - counters[4]] = x; - if (counters[4] > 0) counters[4] -= 1; + counters[4] -= 1; } return sz; } + /** + * @dev The decoder for reading a field + * @param p The offset of bytes array to start decode + * @param bs The bytes array to be decoded + * @param r The in-memory struct + * @return The number of bytes decoded + */ + function _read_packed_repeated_path( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (uint256 len, uint256 size) = ProtoBufRuntime._decode_varint(p, bs); + p += size; + uint256 count = ProtoBufRuntime._count_packed_repeated_varint(p, len, bs); + r.path = new int32[](count); + for (uint256 i = 0; i < count; i++) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + p += sz; + r.path[i] = x; + } + return size + len; + } + // struct decoder /** * @dev The decoder for reading a inner struct field @@ -4746,15 +4108,15 @@ library CompressedExistenceProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_LeafOp(uint256 p, bytes memory bs) + function _decode_Ics23LeafOp(uint256 p, bytes memory bs) internal pure - returns (LeafOp.Data memory, uint) + returns (Ics23LeafOp.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (LeafOp.Data memory r, ) = LeafOp._decode(pointer, bs, sz); + (Ics23LeafOp.Data memory r, ) = Ics23LeafOp._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -4816,16 +4178,21 @@ library CompressedExistenceProof { pointer, bs ); - pointer += LeafOp._encode_nested(r.leaf, pointer, bs); + pointer += Ics23LeafOp._encode_nested(r.leaf, pointer, bs); if (r.path.length != 0) { + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += ProtoBufRuntime._encode_varint( + ProtoBufRuntime._estimate_packed_repeated_int32(r.path), + pointer, + bs + ); for(i = 0; i < r.path.length; i++) { - pointer += ProtoBufRuntime._encode_key( - 4, - ProtoBufRuntime.WireType.Varint, - pointer, - bs) - ; pointer += ProtoBufRuntime._encode_int32(r.path[i], pointer, bs); } } @@ -4874,10 +4241,8 @@ library CompressedExistenceProof { uint256 e;uint256 i; e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); e += 1 + ProtoBufRuntime._sz_lendelim(r.value.length); - e += 1 + ProtoBufRuntime._sz_lendelim(LeafOp._estimate(r.leaf)); - for(i = 0; i < r.path.length; i++) { - e += 1 + ProtoBufRuntime._sz_int32(r.path[i]); - } + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23LeafOp._estimate(r.leaf)); + e += 1 + ProtoBufRuntime._sz_lendelim(ProtoBufRuntime._estimate_packed_repeated_int32(r.path)); return e; } // empty checker @@ -4911,7 +4276,7 @@ library CompressedExistenceProof { function store(Data memory input, Data storage output) internal { output.key = input.key; output.value = input.value; - LeafOp.store(input.leaf, output.leaf); + Ics23LeafOp.store(input.leaf, output.leaf); output.path = input.path; } @@ -4958,16 +4323,16 @@ library CompressedExistenceProof { } } } -//library CompressedExistenceProof +//library Ics23CompressedExistenceProof -library CompressedNonExistenceProof { +library Ics23CompressedNonExistenceProof { //struct definition struct Data { bytes key; - CompressedExistenceProof.Data left; - CompressedExistenceProof.Data right; + Ics23CompressedExistenceProof.Data left; + Ics23CompressedExistenceProof.Data right; } // Decoder section @@ -5007,7 +4372,6 @@ library CompressedNonExistenceProof { returns (Data memory, uint) { Data memory r; - uint[4] memory counters; uint256 fieldId; ProtoBufRuntime.WireType wireType; uint256 bytesRead; @@ -5017,36 +4381,16 @@ library CompressedNonExistenceProof { (fieldId, wireType, bytesRead) = ProtoBufRuntime._decode_key(pointer, bs); pointer += bytesRead; if (fieldId == 1) { - pointer += _read_key(pointer, bs, r, counters); - } - else if (fieldId == 2) { - pointer += _read_left(pointer, bs, r, counters); - } - else if (fieldId == 3) { - pointer += _read_right(pointer, bs, r, counters); - } - - else { - if (wireType == ProtoBufRuntime.WireType.Fixed64) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed64(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Fixed32) { - uint256 size; - (, size) = ProtoBufRuntime._decode_fixed32(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.Varint) { - uint256 size; - (, size) = ProtoBufRuntime._decode_varint(pointer, bs); - pointer += size; - } - if (wireType == ProtoBufRuntime.WireType.LengthDelim) { - uint256 size; - (, size) = ProtoBufRuntime._decode_lendelim(pointer, bs); - pointer += size; - } + pointer += _read_key(pointer, bs, r); + } else + if (fieldId == 2) { + pointer += _read_left(pointer, bs, r); + } else + if (fieldId == 3) { + pointer += _read_right(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); } } @@ -5060,25 +4404,15 @@ library CompressedNonExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_key( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); - if (isNil(r)) { - counters[1] += 1; - } else { - r.key = x; - if (counters[1] > 0) counters[1] -= 1; - } + r.key = x; return sz; } @@ -5087,25 +4421,15 @@ library CompressedNonExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_left( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); - if (isNil(r)) { - counters[2] += 1; - } else { - r.left = x; - if (counters[2] > 0) counters[2] -= 1; - } + (Ics23CompressedExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedExistenceProof(p, bs); + r.left = x; return sz; } @@ -5114,25 +4438,15 @@ library CompressedNonExistenceProof { * @param p The offset of bytes array to start decode * @param bs The bytes array to be decoded * @param r The in-memory struct - * @param counters The counters for repeated fields * @return The number of bytes decoded */ function _read_right( uint256 p, bytes memory bs, - Data memory r, - uint[4] memory counters + Data memory r ) internal pure returns (uint) { - /** - * if `r` is NULL, then only counting the number of fields. - */ - (CompressedExistenceProof.Data memory x, uint256 sz) = _decode_CompressedExistenceProof(p, bs); - if (isNil(r)) { - counters[3] += 1; - } else { - r.right = x; - if (counters[3] > 0) counters[3] -= 1; - } + (Ics23CompressedExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedExistenceProof(p, bs); + r.right = x; return sz; } @@ -5144,15 +4458,15 @@ library CompressedNonExistenceProof { * @return The decoded inner-struct * @return The number of bytes used to decode */ - function _decode_CompressedExistenceProof(uint256 p, bytes memory bs) + function _decode_Ics23CompressedExistenceProof(uint256 p, bytes memory bs) internal pure - returns (CompressedExistenceProof.Data memory, uint) + returns (Ics23CompressedExistenceProof.Data memory, uint) { uint256 pointer = p; (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); pointer += bytesRead; - (CompressedExistenceProof.Data memory r, ) = CompressedExistenceProof._decode(pointer, bs, sz); + (Ics23CompressedExistenceProof.Data memory r, ) = Ics23CompressedExistenceProof._decode(pointer, bs, sz); return (r, sz + bytesRead); } @@ -5205,7 +4519,7 @@ library CompressedNonExistenceProof { pointer, bs ); - pointer += CompressedExistenceProof._encode_nested(r.left, pointer, bs); + pointer += Ics23CompressedExistenceProof._encode_nested(r.left, pointer, bs); pointer += ProtoBufRuntime._encode_key( @@ -5214,7 +4528,7 @@ library CompressedNonExistenceProof { pointer, bs ); - pointer += CompressedExistenceProof._encode_nested(r.right, pointer, bs); + pointer += Ics23CompressedExistenceProof._encode_nested(r.right, pointer, bs); return pointer - offset; } @@ -5260,8 +4574,8 @@ library CompressedNonExistenceProof { ) internal pure returns (uint) { uint256 e; e += 1 + ProtoBufRuntime._sz_lendelim(r.key.length); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.left)); - e += 1 + ProtoBufRuntime._sz_lendelim(CompressedExistenceProof._estimate(r.right)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedExistenceProof._estimate(r.right)); return e; } // empty checker @@ -5286,8 +4600,8 @@ library CompressedNonExistenceProof { */ function store(Data memory input, Data storage output) internal { output.key = input.key; - CompressedExistenceProof.store(input.left, output.left); - CompressedExistenceProof.store(input.right, output.right); + Ics23CompressedExistenceProof.store(input.left, output.left); + Ics23CompressedExistenceProof.store(input.right, output.right); } @@ -5315,7 +4629,7 @@ library CompressedNonExistenceProof { } } } -//library CompressedNonExistenceProof +//library Ics23CompressedNonExistenceProof library PROOFS_PROTO_GLOBAL_ENUMS { @@ -5400,6 +4714,20 @@ library PROOFS_PROTO_GLOBAL_ENUMS { } + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_HashOp( + HashOp[] memory a + ) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_HashOp(a[i])); + } + return e; + } + // Solidity enum definitions enum LengthOp { NO_PREFIX, @@ -5497,5 +4825,19 @@ library PROOFS_PROTO_GLOBAL_ENUMS { revert(); } + + /** + * @dev The estimator for an packed enum array + * @return The number of bytes encoded + */ + function estimate_packed_repeated_LengthOp( + LengthOp[] memory a + ) internal pure returns (uint256) { + uint256 e = 0; + for (uint i = 0; i < a.length; i++) { + e += ProtoBufRuntime._sz_enum(encode_LengthOp(a[i])); + } + return e; + } } -//library PROOFS_PROTO_GLOBAL_ENUMS +//library PROOFS_PROTO_GLOBAL_ENUMS \ No newline at end of file From 1e41626f4542cc87649b464e4671fabd9b0f5769 Mon Sep 17 00:00:00 2001 From: Giulio Date: Mon, 31 Jan 2022 15:31:24 +0100 Subject: [PATCH 7/7] updating the decompress functions with ErrorEnum --- sol/contracts/ics23.sol | 12 +++-- sol/contracts/ics23Compress.sol | 77 +++++++++++++++++++---------- sol/contracts/ics23CompressMock.sol | 19 ++++++- sol/contracts/ics23Proof.sol | 7 ++- 4 files changed, 81 insertions(+), 34 deletions(-) diff --git a/sol/contracts/ics23.sol b/sol/contracts/ics23.sol index 47af0400..dc5b057c 100644 --- a/sol/contracts/ics23.sol +++ b/sol/contracts/ics23.sol @@ -14,7 +14,8 @@ library Ics23 { enum VerifyMembershipError { None, ExistenceProofIsNil, - ProofVerify + ProofVerify, + Decompress } function verifyMembership( Ics23ProofSpec.Data memory spec, @@ -23,7 +24,8 @@ library Ics23 { bytes memory key, bytes memory value ) internal pure returns(VerifyMembershipError){ - Ics23CommitmentProof.Data memory decoProof = Compress.decompress(proof); + (Ics23CommitmentProof.Data memory decoProof, Compress.DecompressEntryError erCode) = Compress.decompress(proof); + if (erCode != Compress.DecompressEntryError.None) return VerifyMembershipError.Decompress; Ics23ExistenceProof.Data memory exiProof = getExistProofForKey(decoProof, key); //require(Ics23ExistenceProof.isNil(exiProof) == false); // dev: getExistProofForKey not available if (Ics23ExistenceProof.isNil(exiProof)) return VerifyMembershipError.ExistenceProofIsNil; @@ -36,7 +38,8 @@ library Ics23 { enum VerifyNonMembershipError { None, NonExistenceProofIsNil, - ProofVerify + ProofVerify, + Decompress } function verifyNonMembership( @@ -45,7 +48,8 @@ library Ics23 { Ics23CommitmentProof.Data memory proof, bytes memory key ) internal pure returns(VerifyNonMembershipError) { - Ics23CommitmentProof.Data memory decoProof = Compress.decompress(proof); + (Ics23CommitmentProof.Data memory decoProof, Compress.DecompressEntryError erCode) = Compress.decompress(proof); + if (erCode != Compress.DecompressEntryError.None) return VerifyNonMembershipError.Decompress; Ics23NonExistenceProof.Data memory nonProof = getNonExistProofForKey(decoProof, key); //require(Ics23NonExistenceProof.isNil(nonProof) == false); // dev: getNonExistProofForKey not available if (Ics23NonExistenceProof.isNil(nonProof)) return VerifyNonMembershipError.NonExistenceProofIsNil; diff --git a/sol/contracts/ics23Compress.sol b/sol/contracts/ics23Compress.sol index 28685ee2..a3a7352a 100644 --- a/sol/contracts/ics23Compress.sol +++ b/sol/contracts/ics23Compress.sol @@ -12,56 +12,79 @@ library Compress { @notice will return a Ics23BatchProof if the input is CompressedBatchProof. Otherwise it will return the input. This is safe to call multiple times (idempotent) */ - function decompress(Ics23CommitmentProof.Data memory proof) internal pure returns(Ics23CommitmentProof.Data memory) { + function decompress( + Ics23CommitmentProof.Data memory proof + ) internal pure returns(Ics23CommitmentProof.Data memory, DecompressEntryError) { //Ics23CompressedBatchProof.isNil() does not work if (Ics23CompressedBatchProof._empty(proof.compressed) == true){ - return proof; + return (proof, DecompressEntryError.None); } - return Ics23CommitmentProof.Data({ - exist: Ics23ExistenceProof.nil(), - nonexist: Ics23NonExistenceProof.nil(), - batch: Ics23BatchProof.Data({ - entries: decompress(proof.compressed) - }), - compressed: Ics23CompressedBatchProof.nil() - }); + (Ics23BatchEntry.Data[] memory entries, DecompressEntryError erCode) = decompress(proof.compressed); + if (erCode != DecompressEntryError.None) return (Ics23CommitmentProof.nil(), erCode); + Ics23CommitmentProof.Data memory retVal; + retVal.exist = Ics23ExistenceProof.nil(); + retVal.nonexist = Ics23NonExistenceProof.nil(); + retVal.compressed = Ics23CompressedBatchProof.nil(); + retVal.batch.entries = entries; + return (retVal, DecompressEntryError.None); } - function decompress(Ics23CompressedBatchProof.Data memory proof) private pure returns(Ics23BatchEntry.Data[] memory) { + function decompress( + Ics23CompressedBatchProof.Data memory proof + ) private pure returns(Ics23BatchEntry.Data[] memory, DecompressEntryError) { Ics23BatchEntry.Data[] memory entries = new Ics23BatchEntry.Data[](proof.entries.length); for(uint i = 0; i < proof.entries.length; i++) { - entries[i] = decompressEntry(proof.entries[i], proof.lookup_inners); + (Ics23BatchEntry.Data memory entry, DecompressEntryError erCode) = decompressEntry(proof.entries[i], proof.lookup_inners); + if (erCode != DecompressEntryError.None) return (entries, erCode); + entries[i] = entry; } - return entries; + return (entries, DecompressEntryError.None); } + enum DecompressEntryError{ + None, + ExistDecompress, + LeftDecompress, + RightDecompress + } function decompressEntry( Ics23CompressedBatchEntry.Data memory entry, Ics23InnerOp.Data[] memory lookup - ) private pure returns(Ics23BatchEntry.Data memory) { + ) private pure returns(Ics23BatchEntry.Data memory, DecompressEntryError) { //Ics23CompressedExistenceProof.isNil does not work if (Ics23CompressedExistenceProof._empty(entry.exist) == false) { - return Ics23BatchEntry.Data({ - exist: decompressExist(entry.exist, lookup), + (Ics23ExistenceProof.Data memory exist, DecompressExistError existErCode) = decompressExist(entry.exist, lookup); + if (existErCode != DecompressExistError.None) return(Ics23BatchEntry.nil(), DecompressEntryError.ExistDecompress); + return (Ics23BatchEntry.Data({ + exist: exist, nonexist: Ics23NonExistenceProof.nil() - }); + }), DecompressEntryError.None); } - return Ics23BatchEntry.Data({ + (Ics23ExistenceProof.Data memory left, DecompressExistError leftErCode) = decompressExist(entry.nonexist.left, lookup); + if (leftErCode != DecompressExistError.None) return(Ics23BatchEntry.nil(), DecompressEntryError.LeftDecompress); + (Ics23ExistenceProof.Data memory right, DecompressExistError rightErCode) = decompressExist(entry.nonexist.right, lookup); + if (rightErCode != DecompressExistError.None) return(Ics23BatchEntry.nil(), DecompressEntryError.RightDecompress); + return (Ics23BatchEntry.Data({ exist: Ics23ExistenceProof.nil(), nonexist: Ics23NonExistenceProof.Data({ key: entry.nonexist.key, - left: decompressExist(entry.nonexist.left, lookup), - right: decompressExist(entry.nonexist.right, lookup) + left: left, + right: right }) - }); + }), DecompressEntryError.None); } + enum DecompressExistError{ + None, + PathLessThanZero, + StepGreaterOrEqualToLength + } function decompressExist( Ics23CompressedExistenceProof.Data memory proof, Ics23InnerOp.Data[] memory lookup - ) private pure returns(Ics23ExistenceProof.Data memory) { + ) private pure returns(Ics23ExistenceProof.Data memory, DecompressExistError) { if (Ics23CompressedExistenceProof._empty(proof)) { - return Ics23ExistenceProof.nil(); + return (Ics23ExistenceProof.nil(), DecompressExistError.None); } Ics23ExistenceProof.Data memory decoProof = Ics23ExistenceProof.Data({ key: proof.key, @@ -70,11 +93,13 @@ library Compress { path : new Ics23InnerOp.Data[](proof.path.length) }); for (uint i = 0; i < proof.path.length; i++) { - require(proof.path[i] >= 0); // dev: proof.path < 0 + //require(proof.path[i] >= 0); // dev: proof.path < 0 + if (proof.path[i] < 0) return (Ics23ExistenceProof.nil(), DecompressExistError.PathLessThanZero); uint step = SafeCast.toUint256(proof.path[i]); - require(step < lookup.length); // dev: step >= lookup.length + //require(step < lookup.length); // dev: step >= lookup.length + if (step >= lookup.length) return (Ics23ExistenceProof.nil(), DecompressExistError.StepGreaterOrEqualToLength); decoProof.path[i] = lookup[step]; } - return decoProof; + return (decoProof, DecompressExistError.None); } } diff --git a/sol/contracts/ics23CompressMock.sol b/sol/contracts/ics23CompressMock.sol index 6098137d..ee9f8009 100644 --- a/sol/contracts/ics23CompressMock.sol +++ b/sol/contracts/ics23CompressMock.sol @@ -1,12 +1,27 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.2; -import {Ics23CommitmentProof} from "./proofs.sol"; +import {Ics23CommitmentProof, Ics23ExistenceProof, Ics23BatchEntry} from "./proofs.sol"; import {Compress} from "./ics23Compress.sol"; contract CompressMock { function decompress(Ics23CommitmentProof.Data memory proof) public pure returns(Ics23CommitmentProof.Data memory) { - return Compress.decompress(proof); + (Ics23CommitmentProof.Data memory proof, Compress.DecompressEntryError erCode) = Compress.decompress(proof); + require(erCode == Compress.DecompressEntryError.None, "CompressMock"); // dev: expand this require to check error code + // nil Data do not parse well when trying to bring it out of the EVM + Ics23CommitmentProof.Data memory retV; + if (Ics23CommitmentProof.isNil(proof)) return retV; + if (Ics23ExistenceProof.isNil(proof.exist)) { + retV.batch.entries = new Ics23BatchEntry.Data[](proof.batch.entries.length); + for(uint i = 0; i < proof.batch.entries.length; i++) { + if (Ics23ExistenceProof.isNil(proof.batch.entries[i].exist)) { + retV.batch.entries[i].nonexist = proof.batch.entries[i].nonexist; + } else { + retV.batch.entries[i].exist = proof.batch.entries[i].exist; + } + } + } + return retV; } } diff --git a/sol/contracts/ics23Proof.sol b/sol/contracts/ics23Proof.sol index 46e2f8ba..589b5043 100644 --- a/sol/contracts/ics23Proof.sol +++ b/sol/contracts/ics23Proof.sol @@ -57,7 +57,8 @@ library Proof{ PathOp, BatchEntriesLength, BatchEntryEmpty, - EmptyProof + EmptyProof, + Decompress } /** @notice calculateRoot determines the root hash that matches the given proof. You must validate the result in what you have in a header. @@ -218,7 +219,9 @@ library Proof{ } } if (Ics23CompressedBatchProof._empty(proof.compressed) == false) { - return calculateRoot(Compress.decompress(proof)); + (Ics23CommitmentProof.Data memory proof, Compress.DecompressEntryError erCode) = Compress.decompress(proof); + if (erCode != Compress.DecompressEntryError.None) return (empty, CalculateRootError.Decompress); + return calculateRoot(proof); } //revert(); // dev: calculateRoot(CommitmentProof) empty proof return (empty, CalculateRootError.EmptyProof);