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..0a0a851f --- /dev/null +++ b/sol/contracts/GoogleProtobufAny.sol @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.10; +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..b72bcce6 --- /dev/null +++ b/sol/contracts/ProtoBufRuntime.sol @@ -0,0 +1,3084 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.10; + + +/** + * @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 { + if (len == 0) { + return; + } + + // 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); + } + + /** + * @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 + * @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)); + } + + /** + * `_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. + * @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..dc5b057c --- /dev/null +++ b/sol/contracts/ics23.sol @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +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"; +import {BytesLib} from "GNSPS/solidity-bytes-utils@0.8.0/contracts/BytesLib.sol"; + +library Ics23 { + + enum VerifyMembershipError { + None, + ExistenceProofIsNil, + ProofVerify, + Decompress + } + 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.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; + Proof.VerifyExistenceError vCode = Proof.verify(exiProof, spec, commitmentRoot, key, value); + if (vCode != Proof.VerifyExistenceError.None) return VerifyMembershipError.ProofVerify; + + return VerifyMembershipError.None; + } + + enum VerifyNonMembershipError { + None, + NonExistenceProofIsNil, + ProofVerify, + Decompress + } + + 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.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; + 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 { + 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( + 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(Ics23BatchProof.isNil(proof.batch) == false) { + for (uint i = 0; i < proof.batch.entries.length; i++) { + 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 Ics23ExistenceProof.nil(); + } + + 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 (Ics23BatchProof.isNil(proof.batch) == false) { + for (uint i = 0; i < proof.batch.entries.length; i++) { + 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 Ics23NonExistenceProof.nil(); + } + + 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(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 new file mode 100644 index 00000000..a3a7352a --- /dev/null +++ b/sol/contracts/ics23Compress.sol @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +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 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, DecompressEntryError) { + //Ics23CompressedBatchProof.isNil() does not work + if (Ics23CompressedBatchProof._empty(proof.compressed) == true){ + return (proof, DecompressEntryError.None); + } + (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, DecompressEntryError) { + Ics23BatchEntry.Data[] memory entries = new Ics23BatchEntry.Data[](proof.entries.length); + for(uint i = 0; i < proof.entries.length; i++) { + (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, DecompressEntryError.None); + } + + enum DecompressEntryError{ + None, + ExistDecompress, + LeftDecompress, + RightDecompress + } + function decompressEntry( + Ics23CompressedBatchEntry.Data memory entry, + Ics23InnerOp.Data[] memory lookup + ) private pure returns(Ics23BatchEntry.Data memory, DecompressEntryError) { + //Ics23CompressedExistenceProof.isNil does not work + if (Ics23CompressedExistenceProof._empty(entry.exist) == false) { + (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); + } + (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: 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, DecompressExistError) { + if (Ics23CompressedExistenceProof._empty(proof)) { + return (Ics23ExistenceProof.nil(), DecompressExistError.None); + } + Ics23ExistenceProof.Data memory decoProof = Ics23ExistenceProof.Data({ + key: proof.key, + value: proof.value, + leaf: proof.leaf, + 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 + 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 + if (step >= lookup.length) return (Ics23ExistenceProof.nil(), DecompressExistError.StepGreaterOrEqualToLength); + decoProof.path[i] = lookup[step]; + } + return (decoProof, DecompressExistError.None); + } +} diff --git a/sol/contracts/ics23CompressMock.sol b/sol/contracts/ics23CompressMock.sol new file mode 100644 index 00000000..ee9f8009 --- /dev/null +++ b/sol/contracts/ics23CompressMock.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +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) { + (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/ics23Mock.sol b/sol/contracts/ics23Mock.sol new file mode 100644 index 00000000..48f2ffe7 --- /dev/null +++ b/sol/contracts/ics23Mock.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +import { + Ics23BatchProof, Ics23CompressedBatchProof, Ics23CommitmentProof, Ics23ProofSpec, Ics23ExistenceProof, Ics23NonExistenceProof +} from "./proofs.sol"; +import {Ics23} from "./ics23.sol"; + + +contract ICS23Mock { + 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( + 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); + } +/* -- 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 new file mode 100644 index 00000000..ab2f1599 --- /dev/null +++ b/sol/contracts/ics23Ops.sol @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +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"; +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 + } + /** + @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( + Ics23LeafOp.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); + (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 + } + 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); + } + + enum CheckAgainstSpecError{ + None, + Hash, + PreHashKey, + PreHashValue, + Length, + MinPrefixLength, + HasPrefix, + MaxPrefixLength + } + /** + @notice will verify the Ics23LeafOp is in the format defined in spec + */ + 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 + 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 + if (hasprefix == false) return CheckAgainstSpecError.HasPrefix; + + return CheckAgainstSpecError.None; + } + + enum ApplyInnerOpError { + None, + ChildLength, + DoHash + } + /** + @notice apply will calculate the hash of the next step, given the hash of the previous step + */ + 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); + (bytes memory hashed, DoHashError code) = doHash(innerOp.hash, preImage); + if (code != DoHashError.None) return (empty, ApplyInnerOpError.DoHash); + + return (hashed, ApplyInnerOpError.None); + } + + /** + @notice will verify the Ics23InnerOp is in the format defined in spec + */ + 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); + //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 + 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 + if (innerOp.prefix.length > maxPrefixLength + maxLeftChildBytes) return CheckAgainstSpecError.MaxPrefixLength; + + 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); + } + return doHash(hashOp, preImage); + } + + enum DoHashError { + None, + Sha512, + 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); + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.KECCAK) { + return (abi.encodePacked(keccak256(preImage)), DoHashError.None); + } + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.RIPEMD160) { + 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)), DoHashError.None); + } + //require(hashOp != PROOFS_PROTO_GLOBAL_ENUMS.HashOp.Sha512); // dev: SHA512 not supported + if (hashOp == PROOFS_PROTO_GLOBAL_ENUMS.HashOp.SHA512) { + 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) { + return (empty, DoHashError.Sha512_256); + } + //revert(); // dev: Unsupported hashOp + return (empty, DoHashError.Unsupported); + } + + 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 + enum DoLengthOpError { + None, + Require32DataLength, + 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); + } + 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), DoLengthOpError.None); + } + if (lenOp == PROOFS_PROTO_GLOBAL_ENUMS.LengthOp.REQUIRE_32_BYTES) { + //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" + 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); + // 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 (abi.encodePacked(littleE, data), DoLengthOpError.None); + } + //revert(); // dev: Unsupported lenOp + return (empty, DoLengthOpError.Unsupported); + } + + 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); + } +} diff --git a/sol/contracts/ics23OpsMock.sol b/sol/contracts/ics23OpsMock.sol new file mode 100644 index 00000000..ba9afcbd --- /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 {Ics23LeafOp, Ics23InnerOp, PROOFS_PROTO_GLOBAL_ENUMS, Ics23ProofSpec} from "./proofs.sol"; + + +contract OpsMock { + 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(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(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(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 + } + 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 new file mode 100644 index 00000000..589b5043 --- /dev/null +++ b/sol/contracts/ics23Proof.sol @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.2; + +import { + 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"; +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{ + bytes constant empty = new bytes(0); + + enum VerifyExistenceError{ + None, + KeyNotMatching, + ValueNotMatching, + CheckSpec, + CalculateRoot, + 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 + */ + function verify( + Ics23ExistenceProof.Data memory proof, + Ics23ProofSpec.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; + } + + enum CalculateRootError { + None, + LeafNil, + LeafOp, + PathOp, + BatchEntriesLength, + BatchEntryEmpty, + 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. + @return CalculateRootError enum giving indication of where error happened, None if verification succeded + */ + 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++) { + Ops.ApplyInnerOpError iCode; + (root, iCode) = Ops.applyOp(proof.path[i], root); + if (iCode != Ops.ApplyInnerOpError.None) return (empty, CalculateRootError.PathOp); + } + + return (root, CalculateRootError.None); + } + + enum CheckAgainstSpecError{ + None, + EmptyLeaf, + OpsCheckAgainstSpec, + 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( + 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) { + 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 == false); // dev: InnerOps depth too long + if (innerOpsDepthTooLong) return CheckAgainstSpecError.InnerOpsDepthTooLong; + } + for(uint i = 0; i < proof.path.length; i++) { + Ops.CheckAgainstSpecError opscCode = Ops.checkAgainstSpec(proof.path[i], spec); + if (opscCode != Ops.CheckAgainstSpecError.None) return CheckAgainstSpecError.OpsCheckAgainstSpec; + } + } + + enum VerifyNonExistenceError { + None, + VerifyLeft, + VerifyRight, + LeftAndRightKeyEmpty, + RightKeyRange, + LeftKeyRange, + RightProofLeftMost, + LeftProofRightMost, + IsLeftNeighbor + } + /** + @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( + Ics23NonExistenceProof.Data memory proof, + Ics23ProofSpec.Data memory spec, + bytes memory commitmentRoot, + bytes memory key + ) internal pure returns(VerifyNonExistenceError) { + bytes memory leftKey; + bytes memory rightKey; + // 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 (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; + + 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 + if (leftKey.length == 0 && rightKey.length == 0) return VerifyNonExistenceError.LeftAndRightKeyEmpty; + // Ensure in valid range + 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 && 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 + 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 + 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 + bool isLeftNeigh = isLeftNeighbor(spec.inner_spec, proof.left.path, proof.right.path); + if (isLeftNeigh == false) return VerifyNonExistenceError.IsLeftNeighbor; + } + + 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(Ics23NonExistenceProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { + if (Ics23ExistenceProof._empty(proof.left) == false) { + return calculateRoot(proof.left); + } + if (Ics23ExistenceProof._empty(proof.right) == false) { + return calculateRoot(proof.right); + } + //revert(); // dev: Nonexistence proof has empty Left and Right proof + return (empty, CalculateRootError.EmptyProof); + } + + /** + @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(Ics23CommitmentProof.Data memory proof) internal pure returns(bytes memory, CalculateRootError) { + if (Ics23ExistenceProof._empty(proof.exist) == false) { + return calculateRoot(proof.exist); + } + if (Ics23NonExistenceProof._empty(proof.nonexist) == false) { + return calculateRoot(proof.nonexist); + } + 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(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 (Ics23NonExistenceProof._empty(proof.batch.entries[0].nonexist) == false) { + return calculateRoot(proof.batch.entries[0].nonexist); + } + } + if (Ics23CompressedBatchProof._empty(proof.compressed) == false) { + (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); + } + + + /** + @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++) { + if (hasPadding(path[i], minPrefix, maxPrefix, suffix) == false){ + return false; + } + } + return true; + } + + /** + @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; + for (uint i = 0; i < path.length; i++) { + if (hasPadding(path[i], minPrefix, maxPrefix, suffix) == false){ + return false; + } + } + + return true; + } + + /** + @notice assumes left and right have common parents checks if left is exactly one slot to the left of right + */ + 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); + if (lCode != OrderFromPaddingError.None) return false; + if (rCode != OrderFromPaddingError.None) return false; + + return rightIdx == leftIdx + 1; + } + + /** + @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( + 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)) { + 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; + } + + enum OrderFromPaddingError { + None, + 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( + 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); + 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 + return (0, OrderFromPaddingError.NotFound); + } + + enum GetPaddingError { + None, + GetPosition + } + /** + @notice determines prefix and suffix with the given spec and position in the tree + */ + function getPadding( + Ics23InnerSpec.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); + 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); + } + + enum GetPositionError { + None, + 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); + for (uint i = 0; i < order.length; i++) { + if (SafeCast.toUint256(order[i]) == branch) return (i, GetPositionError.None); + } + //revert(); // dev: branch not found in order + return (0, GetPositionError.NoFound); + } + + 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; + } + + /** + @return a slice of of InnerOp.Data, array[start..end] + */ + 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]; + } + return slice; + } +} diff --git a/sol/contracts/ics23ProofMock.sol b/sol/contracts/ics23ProofMock.sol new file mode 100644 index 00000000..3c9e3bc0 --- /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 {Ics23ExistenceProof, Ics23ProofSpec, Ics23CommitmentProof} from "./proofs.sol"; + +contract ProofMock { + 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(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(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(Ics23CommitmentProof.Data memory) { + Ics23CommitmentProof.Data memory res = Ics23CommitmentProof.decode(protoMsg); + return res; + } +} diff --git a/sol/contracts/proofs.sol b/sol/contracts/proofs.sol new file mode 100644 index 00000000..c474e92b --- /dev/null +++ b/sol/contracts/proofs.sol @@ -0,0 +1,4843 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.10; +import "./ProtoBufRuntime.sol"; +import "./GoogleProtobufAny.sol"; + +library Ics23ExistenceProof { + + + //struct definition + struct Data { + bytes key; + bytes value; + Ics23LeafOp.Data leaf; + Ics23InnerOp.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); + } 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; + 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 == 4) { + pointer += _read_unpacked_repeated_path(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + 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 + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.key = x; + 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_value( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.value = x; + 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_leaf( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23LeafOp.Data memory x, uint256 sz) = _decode_Ics23LeafOp(p, bs); + r.leaf = x; + 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_unpacked_repeated_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. + */ + (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; + 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_Ics23LeafOp(uint256 p, bytes memory bs) + internal + pure + returns (Ics23LeafOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23LeafOp.Data memory r, ) = Ics23LeafOp._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_Ics23InnerOp(uint256 p, bytes memory bs) + internal + pure + returns (Ics23InnerOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23InnerOp.Data memory r, ) = Ics23InnerOp._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 += Ics23LeafOp._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 += Ics23InnerOp._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(Ics23LeafOp._estimate(r.leaf)); + for(i = 0; i < r.path.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23InnerOp._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; + Ics23LeafOp.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, Ics23InnerOp.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + 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]; + } + 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 Ics23ExistenceProof + +library Ics23NonExistenceProof { + + + //struct definition + struct Data { + bytes key; + Ics23ExistenceProof.Data left; + Ics23ExistenceProof.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; + 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); + } 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); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.key = x; + 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_left( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.left = x; + 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_right( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.right = x; + 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_Ics23ExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23ExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23ExistenceProof.Data memory r, ) = Ics23ExistenceProof._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 += Ics23ExistenceProof._encode_nested(r.left, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23ExistenceProof._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(Ics23ExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23ExistenceProof._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; + Ics23ExistenceProof.store(input.left, output.left); + Ics23ExistenceProof.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 Ics23NonExistenceProof + +library Ics23CommitmentProof { + + + //struct definition + struct Data { + Ics23ExistenceProof.Data exist; + Ics23NonExistenceProof.Data nonexist; + Ics23BatchProof.Data batch; + Ics23CompressedBatchProof.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; + 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); + } 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); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.exist = x; + 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_nonexist( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23NonExistenceProof.Data memory x, uint256 sz) = _decode_Ics23NonExistenceProof(p, bs); + r.nonexist = x; + 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_batch( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23BatchProof.Data memory x, uint256 sz) = _decode_Ics23BatchProof(p, bs); + r.batch = x; + 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_compressed( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23CompressedBatchProof.Data memory x, uint256 sz) = _decode_Ics23CompressedBatchProof(p, bs); + r.compressed = x; + 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_Ics23ExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23ExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23ExistenceProof.Data memory r, ) = Ics23ExistenceProof._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_Ics23NonExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23NonExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23NonExistenceProof.Data memory r, ) = Ics23NonExistenceProof._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_Ics23BatchProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23BatchProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23BatchProof.Data memory r, ) = Ics23BatchProof._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_Ics23CompressedBatchProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23CompressedBatchProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23CompressedBatchProof.Data memory r, ) = Ics23CompressedBatchProof._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 += Ics23ExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23NonExistenceProof._encode_nested(r.nonexist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23BatchProof._encode_nested(r.batch, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 4, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23CompressedBatchProof._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(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 + + 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 { + Ics23ExistenceProof.store(input.exist, output.exist); + Ics23NonExistenceProof.store(input.nonexist, output.nonexist); + Ics23BatchProof.store(input.batch, output.batch); + Ics23CompressedBatchProof.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 Ics23CommitmentProof + +library Ics23LeafOp { + + + //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; + 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); + } 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); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + r.hash = x; + 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_prehash_key( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + r.prehash_key = x; + 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_prehash_value( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + r.prehash_value = x; + 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_length( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.LengthOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_LengthOp(tmp); + r.length = x; + 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_prefix( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.prefix = x; + 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 Ics23LeafOp + +library Ics23InnerOp { + + + //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; + 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); + } 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); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_hash( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + r.hash = x; + 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_prefix( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.prefix = x; + 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_suffix( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.suffix = x; + 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 Ics23InnerOp + +library Ics23ProofSpec { + + + //struct definition + struct Data { + Ics23LeafOp.Data leaf_spec; + Ics23InnerSpec.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; + 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); + } 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); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_leaf_spec( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23LeafOp.Data memory x, uint256 sz) = _decode_Ics23LeafOp(p, bs); + r.leaf_spec = x; + 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_inner_spec( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23InnerSpec.Data memory x, uint256 sz) = _decode_Ics23InnerSpec(p, bs); + r.inner_spec = x; + 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_max_depth( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + r.max_depth = x; + 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_min_depth( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + r.min_depth = x; + 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_Ics23LeafOp(uint256 p, bytes memory bs) + internal + pure + returns (Ics23LeafOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23LeafOp.Data memory r, ) = Ics23LeafOp._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_Ics23InnerSpec(uint256 p, bytes memory bs) + internal + pure + returns (Ics23InnerSpec.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23InnerSpec.Data memory r, ) = Ics23InnerSpec._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 += Ics23LeafOp._encode_nested(r.leaf_spec, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23InnerSpec._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(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; + } + // 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 { + 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; + + } + + + + //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 Ics23ProofSpec + +library Ics23InnerSpec { + + + //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) { + if (wireType == ProtoBufRuntime.WireType.LengthDelim) { + 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; + 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 && 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); + } + + // 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_unpacked_repeated_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; + 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 + * @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 + ) internal pure returns (uint) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + r.child_size = x; + 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_min_prefix_length( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + r.min_prefix_length = x; + 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_max_prefix_length( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int32 x, uint256 sz) = ProtoBufRuntime._decode_int32(p, bs); + r.max_prefix_length = x; + 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_empty_child( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.empty_child = x; + 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_hash( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (int64 tmp, uint256 sz) = ProtoBufRuntime._decode_enum(p, bs); + PROOFS_PROTO_GLOBAL_ENUMS.HashOp x = PROOFS_PROTO_GLOBAL_ENUMS.decode_HashOp(tmp); + r.hash = x; + 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) { + 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_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; + 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); + 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 Ics23InnerSpec + +library Ics23BatchProof { + + + //struct definition + struct Data { + Ics23BatchEntry.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_unpacked_repeated_entries(pointer, bs, nil(), counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + + } + pointer = offset; + 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_unpacked_repeated_entries(pointer, bs, r, counters); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + } + 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_unpacked_repeated_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. + */ + (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; + 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_Ics23BatchEntry(uint256 p, bytes memory bs) + internal + pure + returns (Ics23BatchEntry.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23BatchEntry.Data memory r, ) = Ics23BatchEntry._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 += Ics23BatchEntry._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(Ics23BatchEntry._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, Ics23BatchEntry.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + 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]; + } + 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 Ics23BatchProof + +library Ics23BatchEntry { + + + //struct definition + struct Data { + Ics23ExistenceProof.Data exist; + Ics23NonExistenceProof.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; + 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); + } else + if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23ExistenceProof.Data memory x, uint256 sz) = _decode_Ics23ExistenceProof(p, bs); + r.exist = x; + 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_nonexist( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23NonExistenceProof.Data memory x, uint256 sz) = _decode_Ics23NonExistenceProof(p, bs); + r.nonexist = x; + 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_Ics23ExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23ExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23ExistenceProof.Data memory r, ) = Ics23ExistenceProof._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_Ics23NonExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23NonExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23NonExistenceProof.Data memory r, ) = Ics23NonExistenceProof._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 += Ics23ExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23NonExistenceProof._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(Ics23ExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23NonExistenceProof._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 { + Ics23ExistenceProof.store(input.exist, output.exist); + Ics23NonExistenceProof.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 Ics23BatchEntry + +library Ics23CompressedBatchProof { + + + //struct definition + struct Data { + Ics23CompressedBatchEntry.Data[] entries; + Ics23InnerOp.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_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; + 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_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); + } + + // 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_unpacked_repeated_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. + */ + (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; + 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_unpacked_repeated_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. + */ + (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; + 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_Ics23CompressedBatchEntry(uint256 p, bytes memory bs) + internal + pure + returns (Ics23CompressedBatchEntry.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23CompressedBatchEntry.Data memory r, ) = Ics23CompressedBatchEntry._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_Ics23InnerOp(uint256 p, bytes memory bs) + internal + pure + returns (Ics23InnerOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23InnerOp.Data memory r, ) = Ics23InnerOp._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 += Ics23CompressedBatchEntry._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 += Ics23InnerOp._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(Ics23CompressedBatchEntry._estimate(r.entries[i])); + } + for(i = 0; i < r.lookup_inners.length; i++) { + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23InnerOp._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, Ics23CompressedBatchEntry.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + 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]; + } + 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, Ics23InnerOp.Data memory value) internal pure { + /** + * First resize the array. Then add the new element to the end. + */ + 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]; + } + 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 Ics23CompressedBatchProof + +library Ics23CompressedBatchEntry { + + + //struct definition + struct Data { + Ics23CompressedExistenceProof.Data exist; + Ics23CompressedNonExistenceProof.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; + 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); + } else + if (fieldId == 2) { + pointer += _read_nonexist(pointer, bs, r); + } else + { + pointer += ProtoBufRuntime._skip_field_decode(wireType, pointer, bs); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_exist( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23CompressedExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedExistenceProof(p, bs); + r.exist = x; + 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_nonexist( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23CompressedNonExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedNonExistenceProof(p, bs); + r.nonexist = x; + 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_Ics23CompressedExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23CompressedExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23CompressedExistenceProof.Data memory r, ) = Ics23CompressedExistenceProof._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_Ics23CompressedNonExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23CompressedNonExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23CompressedNonExistenceProof.Data memory r, ) = Ics23CompressedNonExistenceProof._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 += Ics23CompressedExistenceProof._encode_nested(r.exist, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 2, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23CompressedNonExistenceProof._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(Ics23CompressedExistenceProof._estimate(r.exist)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedNonExistenceProof._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 { + Ics23CompressedExistenceProof.store(input.exist, output.exist); + Ics23CompressedNonExistenceProof.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 Ics23CompressedBatchEntry + +library Ics23CompressedExistenceProof { + + + //struct definition + struct Data { + bytes key; + bytes value; + Ics23LeafOp.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); + } 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) { + 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; + 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 == 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); + } + + // 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 + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.key = x; + 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_value( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.value = x; + 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_leaf( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23LeafOp.Data memory x, uint256 sz) = _decode_Ics23LeafOp(p, bs); + r.leaf = x; + 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_unpacked_repeated_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; + 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 + * @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_Ics23LeafOp(uint256 p, bytes memory bs) + internal + pure + returns (Ics23LeafOp.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23LeafOp.Data memory r, ) = Ics23LeafOp._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 += 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_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(Ics23LeafOp._estimate(r.leaf)); + e += 1 + ProtoBufRuntime._sz_lendelim(ProtoBufRuntime._estimate_packed_repeated_int32(r.path)); + 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; + Ics23LeafOp.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 Ics23CompressedExistenceProof + +library Ics23CompressedNonExistenceProof { + + + //struct definition + struct Data { + bytes key; + Ics23CompressedExistenceProof.Data left; + Ics23CompressedExistenceProof.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; + 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); + } 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); + } + + } + 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 + * @return The number of bytes decoded + */ + function _read_key( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs); + r.key = x; + 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_left( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23CompressedExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedExistenceProof(p, bs); + r.left = x; + 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_right( + uint256 p, + bytes memory bs, + Data memory r + ) internal pure returns (uint) { + (Ics23CompressedExistenceProof.Data memory x, uint256 sz) = _decode_Ics23CompressedExistenceProof(p, bs); + r.right = x; + 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_Ics23CompressedExistenceProof(uint256 p, bytes memory bs) + internal + pure + returns (Ics23CompressedExistenceProof.Data memory, uint) + { + uint256 pointer = p; + (uint256 sz, uint256 bytesRead) = ProtoBufRuntime._decode_varint(pointer, bs); + pointer += bytesRead; + (Ics23CompressedExistenceProof.Data memory r, ) = Ics23CompressedExistenceProof._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 += Ics23CompressedExistenceProof._encode_nested(r.left, pointer, bs); + + + pointer += ProtoBufRuntime._encode_key( + 3, + ProtoBufRuntime.WireType.LengthDelim, + pointer, + bs + ); + pointer += Ics23CompressedExistenceProof._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(Ics23CompressedExistenceProof._estimate(r.left)); + e += 1 + ProtoBufRuntime._sz_lendelim(Ics23CompressedExistenceProof._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; + Ics23CompressedExistenceProof.store(input.left, output.left); + Ics23CompressedExistenceProof.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 Ics23CompressedNonExistenceProof + +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(); + } + + + /** + * @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, + 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(); + } + + + /** + * @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 \ No newline at end of file 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..f3633e71 --- /dev/null +++ b/sol/tests/helpers.py @@ -0,0 +1,33 @@ +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"] + ] + } + 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..fdcff8c3 --- /dev/null +++ b/sol/tests/test_ics23compress.py @@ -0,0 +1,37 @@ +from brownie import accounts, CompressMock, ProofMock +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(CompressMock) + + +@pytest.fixture +def proof(): + return accounts[0].deploy(ProofMock) + + +@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..a1ff8cf4 --- /dev/null +++ b/sol/tests/test_ics23ops.py @@ -0,0 +1,62 @@ +from brownie import accounts, OpsMock +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(OpsMock) + + +@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..e31591f2 --- /dev/null +++ b/sol/tests/test_ics23proof.py @@ -0,0 +1,35 @@ +from brownie import accounts, ProofMock +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(ProofMock) + + +@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..e4bacb3f --- /dev/null +++ b/sol/tests/test_ics23vectors.py @@ -0,0 +1,47 @@ +from brownie import accounts, ICS23Mock, ProofMock +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(ICS23Mock) + + +@pytest.fixture +def proof(): + return accounts[0].deploy(ProofMock) + + +@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"])