diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index eaf23c8..b87a138 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -36,4 +36,6 @@ jobs: - name: Run Cairo tests env: RPC_URL_MAINNET: ${{ secrets.RPC_URL_MAINNET }} - run: source ./tools/make/cairo_tests.sh \ No newline at end of file + run: source ./tools/make/cairo_tests.sh + - name: Run MPT tests + run: source ./tools/make/fuzzer.sh tests/fuzzing/mpt.cairo --ci \ No newline at end of file diff --git a/.gitignore b/.gitignore index 11c15cd..9c619db 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,8 @@ out/ .env .encryptedKey broadcast/ - +*.idea +tests/rust/target node_modules package-lock.json @@ -27,3 +28,6 @@ package-lock.json src/.DS_Store solidity-verifier/lib/* +*.log + +!tests/fuzzing/fixtures/*.json \ No newline at end of file diff --git a/Makefile b/Makefile index bdb912d..72e8c3c 100644 --- a/Makefile +++ b/Makefile @@ -33,4 +33,7 @@ test-full: format-cairo: @echo "Format all .cairo files" - ./tools/make/format_cairo_files.sh \ No newline at end of file + ./tools/make/format_cairo_files.sh + +fuzz-mpt: + ./tools/make/fuzzer.sh tests/fuzzing/mpt.cairo \ No newline at end of file diff --git a/lib/mpt.cairo b/lib/mpt.cairo index a0c9c5e..228f980 100644 --- a/lib/mpt.cairo +++ b/lib/mpt.cairo @@ -8,20 +8,28 @@ from lib.rlp_little import ( extract_nibble_at_byte_pos, extract_n_bytes_from_le_64_chunks_array, extract_le_hash_from_le_64_chunks_array, - assert_subset_in_key, - extract_nibble_from_key, + assert_subset_in_key_be, + extract_nibble_from_key_be, + n_nibbles_in_key, +) +from lib.utils import ( + felt_divmod, + felt_divmod_8, + word_reverse_endian_64, + get_felt_bitlength_128, + uint256_reverse_endian_no_padding, + get_uint256_bit_length, + n_bits_to_n_nibbles, ) -from lib.utils import felt_divmod, felt_divmod_8, word_reverse_endian_64, get_felt_bitlength_128 // Verify a Merkle Patricia Tree proof. // params: // - mpt_proof: the proof to verify as an array of nodes, each node being an array of little endian 8 bytes chunks. // - mpt_proof_bytes_len: array of the length in bytes of each node // - mpt_proof_len: number of nodes in the proof -// - key_little: the key to verify as a little endian bytes Uint256 -// - n_nibbles_already_checked: the number of nibbles already checked in the key. Should start with 0. -// - node_index: the index of the next node to verify. Should start with 0. -// - hash_to_assert: the current hash to assert for the current node. Should start with the root of the MPT. +// - key_be: the key to verify as a big endian Uint256 number. +// - key_be_leading_zeroes_nibbles: the number of leading zeroes nibbles in the key. If the key is 0x007, then 3. +// - root: the root of the MPT as a little endian Uint256 number. // - pow2_array: array of powers of 2. // returns: // - the value of the proof as a felt* array of little endian 8 bytes chunks. @@ -30,7 +38,52 @@ func verify_mpt_proof{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: mpt_proof: felt**, mpt_proof_bytes_len: felt*, mpt_proof_len: felt, - key_little: Uint256, + key_be: Uint256, + key_be_leading_zeroes_nibbles: felt, + root: Uint256, + pow2_array: felt*, +) -> (value: felt*, value_len: felt) { + // %{ print(f"Veryfing key 0x{'0'*ids.key_be_leading_zeroes_nibbles}{hex(ids.key_be.low+2**128*ids.key_be.high)[2:]}") %} + // Verify the key is a valid Uint256 number. + assert [range_check_ptr] = key_be.low; + assert [range_check_ptr + 1] = key_be.high; + // Verify the number of leading zeroes nibbles in the key is valid. + assert [range_check_ptr + 2] = key_be_leading_zeroes_nibbles; + tempvar range_check_ptr = range_check_ptr + 3; + // Count the number of nibbles in the key (excluding leading zeroes). + let (num_nibbles_in_key_without_leading_zeroes) = n_nibbles_in_key(key_be, pow2_array); + let num_nibbles_in_key = num_nibbles_in_key_without_leading_zeroes + + key_be_leading_zeroes_nibbles; + // %{ print(f"num_nibbles_in_key: {ids.num_nibbles_in_key}, key_be_leading_zeroes_nibbles: {ids.key_be_leading_zeroes_nibbles}") %} + // Verify the total number of nibbles in the key is in the range [0, 64]. + assert [range_check_ptr] = 64 - num_nibbles_in_key; + tempvar range_check_ptr = range_check_ptr + 1; + + return verify_mpt_proof_inner( + mpt_proof=mpt_proof, + mpt_proof_bytes_len=mpt_proof_bytes_len, + mpt_proof_len=mpt_proof_len, + key_be=key_be, + key_be_nibbles=num_nibbles_in_key_without_leading_zeroes, + key_be_leading_zeroes_nibbles=key_be_leading_zeroes_nibbles, + n_nibbles_already_checked=0, + node_index=0, + hash_to_assert=root, + pow2_array=pow2_array, + ); +} + +// Inner function for verify_mpt_proof. +// Should not be called directly. +func verify_mpt_proof_inner{ + range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: KeccakBuiltin* +}( + mpt_proof: felt**, + mpt_proof_bytes_len: felt*, + mpt_proof_len: felt, + key_be: Uint256, + key_be_nibbles: felt, + key_be_leading_zeroes_nibbles: felt, n_nibbles_already_checked: felt, node_index: felt, hash_to_assert: Uint256, @@ -42,10 +95,10 @@ func verify_mpt_proof{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: // Last node : item of interest is the value. // Check that the hash of the last node is the expected one. // Check that the final accumulated key is the expected one. - // Check the number of bytes in the key is equal to the number of bytes checked in the key. + // Check the total number of nibbles in the key is equal to the number of nibbles checked in the key. let (node_hash: Uint256) = keccak(mpt_proof[node_index], mpt_proof_bytes_len[node_index]); - %{ print(f"node_hash : {hex(ids.node_hash.low + 2**128*ids.node_hash.high)}") %} - %{ print(f"hash_to_assert : {hex(ids.hash_to_assert.low + 2**128*ids.hash_to_assert.high)}") %} + // %{ print(f"node_hash : {hex(ids.node_hash.low + 2**128*ids.node_hash.high)}") %} + // %{ print(f"hash_to_assert : {hex(ids.hash_to_assert.low + 2**128*ids.hash_to_assert.high)}") %} assert node_hash.low - hash_to_assert.low = 0; assert node_hash.high - hash_to_assert.high = 0; @@ -54,65 +107,41 @@ func verify_mpt_proof{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: bytes_len=mpt_proof_bytes_len[node_index], pow2_array=pow2_array, last_node=1, - key_little=key_little, + key_be=key_be, + key_be_nibbles=key_be_nibbles, + key_be_leading_zeroes_nibbles=key_be_leading_zeroes_nibbles, n_nibbles_already_checked=n_nibbles_already_checked, ); - local key_bits; - with pow2_array { - if (key_little.high != 0) { - let key_bit_high = get_felt_bitlength_128(key_little.high); - assert key_bits = 128 + key_bit_high; - } else { - let key_bit_low = get_felt_bitlength_128(key_little.low); - assert key_bits = key_bit_low; - } - } - local n_bytes_in_key; - let (n_bytes_in_key_tmp, rem) = felt_divmod_8(key_bits); - - if (n_bytes_in_key_tmp == 0) { - assert n_bytes_in_key = 1; - } else { - if (rem != 0) { - assert n_bytes_in_key = n_bytes_in_key_tmp + 1; - } else { - assert n_bytes_in_key = n_bytes_in_key_tmp; - } - } - - local n_bytes_checked; - let (n_bytes_checked_tmp, rem) = felt_divmod(n_nibbles_checked, 2); - if (rem != 0) { - assert n_bytes_checked = n_bytes_checked_tmp + 1; - } else { - assert n_bytes_checked = n_bytes_checked_tmp; - } - assert n_bytes_in_key = n_bytes_checked; + assert key_be_leading_zeroes_nibbles + key_be_nibbles = n_nibbles_checked; return (item_of_interest, item_of_interest_len); } else { // Not last node : item of interest is the hash of the next node. // Check that the hash of the current node is the expected one. let (node_hash: Uint256) = keccak(mpt_proof[node_index], mpt_proof_bytes_len[node_index]); - %{ print(f"node_hash : {hex(ids.node_hash.low + 2**128*ids.node_hash.high)}") %} - %{ print(f"hash_to_assert : {hex(ids.hash_to_assert.low + 2**128*ids.hash_to_assert.high)}") %} + // %{ print(f"node_hash : {hex(ids.node_hash.low + 2**128*ids.node_hash.high)}") %} + // %{ print(f"hash_to_assert : {hex(ids.hash_to_assert.low + 2**128*ids.hash_to_assert.high)}") %} assert node_hash.low - hash_to_assert.low = 0; assert node_hash.high - hash_to_assert.high = 0; - %{ print(f"\t Hash assert for node {ids.node_index} passed.") %} + // %{ print(f"\t Hash assert for node {ids.node_index} passed.") %} let (n_nibbles_checked, item_of_interest, item_of_interest_len) = decode_node_list_lazy( rlp=mpt_proof[node_index], bytes_len=mpt_proof_bytes_len[node_index], pow2_array=pow2_array, last_node=0, - key_little=key_little, + key_be=key_be, + key_be_nibbles=key_be_nibbles, + key_be_leading_zeroes_nibbles=key_be_leading_zeroes_nibbles, n_nibbles_already_checked=n_nibbles_already_checked, ); - return verify_mpt_proof( + return verify_mpt_proof_inner( mpt_proof=mpt_proof, mpt_proof_bytes_len=mpt_proof_bytes_len, mpt_proof_len=mpt_proof_len, - key_little=key_little, + key_be=key_be, + key_be_nibbles=key_be_nibbles, + key_be_leading_zeroes_nibbles=key_be_leading_zeroes_nibbles, n_nibbles_already_checked=n_nibbles_checked, node_index=node_index + 1, hash_to_assert=[cast(item_of_interest, Uint256*)], @@ -127,7 +156,9 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( bytes_len: felt, pow2_array: felt*, last_node: felt, - key_little: Uint256, + key_be: Uint256, + key_be_nibbles: felt, + key_be_leading_zeroes_nibbles: felt, n_nibbles_already_checked: felt, ) -> (n_nibbles_already_checked: felt, item_of_interest: felt*, item_of_interest_len: felt) { alloc_locals; @@ -138,10 +169,10 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( %{ if 0xc0 <= ids.list_prefix <= 0xf7: ids.long_short_list = 0 - print("List type : short") + #print("List type : short") elif 0xf8 <= ids.list_prefix <= 0xff: ids.long_short_list = 1 - print("List type: long") + #print("List type: long") else: print("Not a list.") %} @@ -196,6 +227,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( tempvar range_check_ptr = range_check_ptr + 5; } else { // Single byte + // %{ print(f"First item is single byte, computing second item") %} assert [range_check_ptr + 3] = 0x7f - first_item_prefix; assert first_item_len = 1; assert second_item_starts_at_byte = first_item_start_offset + first_item_len; @@ -218,13 +250,13 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( %{ if 0x00 <= ids.second_item_prefix <= 0x7f: ids.second_item_type = 0 - print(f"2nd item : single byte") + #print(f"2nd item : single byte") elif 0x80 <= ids.second_item_prefix <= 0xb7: ids.second_item_type = 1 - print(f"2nd item : short string {ids.second_item_prefix - 0x80} bytes") + #print(f"2nd item : short string {ids.second_item_prefix - 0x80} bytes") elif 0xb8 <= ids.second_item_prefix <= 0xbf: ids.second_item_type = 2 - print(f"2nd item : long string (len_len {ids.second_item_prefix - 0xb7} bytes)") + #print(f"2nd item : long string (len_len {ids.second_item_prefix - 0xb7} bytes)") else: print(f"2nd item : unknown type {ids.second_item_prefix}") %} @@ -292,7 +324,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( tempvar range_check_ptr = range_check_ptr; } - %{ print(f"second_item_long_string_len : {ids.second_item_bytes_len} bytes") %} + // %{ print(f"second_item_long_string_len : {ids.second_item_bytes_len} bytes") %} assert third_item_starts_at_byte = second_item_starts_at_byte + 1 + len_len + second_item_bytes_len; assert range_check_ptr_f = range_check_ptr; @@ -305,7 +337,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( // %{ print(f"third item starts at byte {ids.third_item_starts_at_byte}") %} if (third_item_starts_at_byte == bytes_len) { - %{ print("two items => Leaf/Extension case") %} + // %{ print("two items => Leaf/Extension case") %} // Node's list has only 2 items : it's a leaf or an extension. // Regardless, we need to decode the first item (key or key_end) and the second item (hash or value). @@ -318,19 +350,19 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( let first_item_key_prefix = extract_nibble_at_byte_pos( rlp[0], first_item_start_offset + first_item_type, 0, pow2_array ); - %{ - prefix = ids.first_item_key_prefix - if prefix == 0: - print("First item is an extension node, even number of nibbles") - elif prefix == 1: - print("First item is an extension node, odd number of nibbles") - elif prefix == 2: - print("First item is a leaf node, even number of nibbles") - elif prefix == 3: - print("First item is a leaf node, odd number of nibbles") - else: - raise Exception(f"Unknown prefix {prefix} for MPT node with 2 items") - %} + // %{ + // prefix = ids.first_item_key_prefix + // if prefix == 0: + // print("First item is an extension node, even number of nibbles") + // elif prefix == 1: + // print("First item is an extension node, odd number of nibbles") + // elif prefix == 2: + // print("First item is a leaf node, even number of nibbles") + // elif prefix == 3: + // print("First item is a leaf node, odd number of nibbles") + // else: + // raise Exception(f"Unknown prefix {prefix} for MPT node with 2 items") + // %} local odd: felt; if (first_item_key_prefix == 0) { assert odd = 0; @@ -342,49 +374,65 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( assert odd = 1; } } - tempvar n_nibbles_in_first_item = 2 * first_item_len - odd; - %{ print(f"n_nibbles_in_first_item : {ids.n_nibbles_in_first_item}") %} - // Extract the key or key_end. - let (local first_item_value_start_word, local first_item_value_start_offset) = felt_divmod( - first_item_start_offset + first_item_type + 1 - odd, 8 - ); - let ( - extracted_key_subset, extracted_key_subset_len - ) = extract_n_bytes_from_le_64_chunks_array( - rlp, - first_item_value_start_word, - first_item_value_start_offset, - first_item_len - first_item_type + odd, - pow2_array, - ); - %{ print(f"nibbles already checked: {ids.n_nibbles_already_checked}") %} local range_check_ptr_f; local bitwise_ptr_f: BitwiseBuiltin*; local n_nibbles_already_checked_f; local pow2_array_f: felt*; if (first_item_type != 0) { + tempvar n_nibbles_in_first_item = 2 * (first_item_len - 1) + odd; + // %{ print(f"n_nibbles_in_first_item : {ids.n_nibbles_in_first_item}") %} + // Extract the key or key_end. start offset + 1 (item prefix) + 1 (key prefix) - odd (1 if to include prefix's byte in case the nibbles are odd). + let first_item_value_starts_at_byte = first_item_start_offset + 2 - odd; + // %{ print(f"\t {ids.first_item_value_starts_at_byte=} \n\t {ids.first_item_start_offset=} \n\t {ids.first_item_type=} \n\t {ids.odd=} \n\t {ids.first_item_len=} \n\t {ids.first_item_type+ids.odd=} \n\t {ids.first_item_start_offset+ids.first_item_type+1-ids.odd=}") %} + let ( + local first_item_value_start_word, local first_item_value_start_offset + ) = felt_divmod(first_item_value_starts_at_byte, 8); + let n_bytes_to_extract = first_item_len - 1 + odd; // - first_item_type + odd; + // %{ print(f"n_bytes_to_extract : {ids.n_bytes_to_extract}") %} + let ( + extracted_key_subset, extracted_key_subset_len + ) = extract_n_bytes_from_le_64_chunks_array( + rlp, + first_item_value_start_word, + first_item_value_start_offset, + n_bytes_to_extract, + pow2_array, + ); + + // %{ + // print(f"nibbles already checked: {ids.n_nibbles_already_checked}") + // if ids.extracted_key_subset_len == 1: + // print(f"Extracted key subset : {hex(memory[ids.extracted_key_subset])}") + // %} // If the first item is not a single byte, verify subset in key. - let (n_nibbles_asserted) = assert_subset_in_key( + assert_subset_in_key_be( key_subset=extracted_key_subset, key_subset_len=extracted_key_subset_len, key_subset_nibble_len=n_nibbles_in_first_item, - key_little=key_little, + key_be=key_be, + key_be_nibbles=key_be_nibbles, + key_be_leading_zeroes_nibbles=key_be_leading_zeroes_nibbles, n_nibbles_already_checked=n_nibbles_already_checked, cut_nibble=odd, pow2_array=pow2_array, ); assert range_check_ptr_f = range_check_ptr; assert bitwise_ptr_f = bitwise_ptr; - assert n_nibbles_already_checked_f = n_nibbles_already_checked + n_nibbles_asserted; + assert n_nibbles_already_checked_f = n_nibbles_already_checked + + n_nibbles_in_first_item; assert pow2_array_f = pow2_array; } else { // if the first item is a single byte if (odd != 0) { // If the first item has an odd number of nibbles, since there are two nibbles in one byte, the second nibble needs to be checked - let key_nibble = extract_nibble_from_key( - key_little, n_nibbles_already_checked, pow2_array + let key_nibble = extract_nibble_from_key_be( + key_be, + key_be_nibbles, + key_be_leading_zeroes_nibbles, + n_nibbles_already_checked, + pow2_array, ); let (_, first_item_nibble) = felt_divmod(first_item_prefix, 2 ** 4); assert key_nibble = first_item_nibble; @@ -406,14 +454,17 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( let n_nibbles_already_checked = n_nibbles_already_checked_f; // Extract the hash or value. - + let (second_item_value_starts_word, second_item_value_start_offset) = felt_divmod( + second_item_value_starts_at_byte, 8 + ); if (last_node != 0) { // Extract value - let (value_starts_word, value_start_offset) = felt_divmod( - second_item_value_starts_at_byte, 8 - ); let (value, value_len) = extract_n_bytes_from_le_64_chunks_array( - rlp, value_starts_word, value_start_offset, second_item_bytes_len, pow2_array + rlp, + second_item_value_starts_word, + second_item_value_start_offset, + second_item_bytes_len, + pow2_array, ); return ( n_nibbles_already_checked=n_nibbles_already_checked, @@ -422,9 +473,10 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( ); } else { // Extract hash (32 bytes) + // %{ print(f"Extracting hash in leaf/node case)") %} assert second_item_bytes_len = 32; let (local hash_le: Uint256) = extract_le_hash_from_le_64_chunks_array( - rlp, second_item_starts_at_word, second_item_start_offset, pow2_array + rlp, second_item_value_starts_word, second_item_value_start_offset, pow2_array ); return ( n_nibbles_already_checked=n_nibbles_already_checked, @@ -435,7 +487,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( } else { // Node has more than 2 items : it's a branch. if (last_node != 0) { - %{ print(f"Branch case, last node : yes") %} + // %{ print(f"Branch case, last node : yes") %} // Branch is the last node in the proof. We need to extract the last item (17th). // Key should already be fully checked at this point. @@ -456,21 +508,25 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( return (n_nibbles_already_checked, last_item, last_item_bytes_len); } else { - %{ print(f"Branch case, last node : no") %} + // %{ print(f"Branch case, last node : no") %} // Branch is not the last node in the proof. We need to extract the hash corresponding to the next nibble of the key. // Get the next nibble of the key. - let next_key_nibble = extract_nibble_from_key( - key_little, n_nibbles_already_checked, pow2_array + let next_key_nibble = extract_nibble_from_key_be( + key_be, + key_be_nibbles, + key_be_leading_zeroes_nibbles, + n_nibbles_already_checked, + pow2_array, ); - %{ print(f"Next Key nibble {ids.next_key_nibble}") %} + // %{ print(f"Next Key nibble {ids.next_key_nibble}") %} local item_of_interest_start_word: felt; local item_of_interest_start_offset: felt; local range_check_ptr_f; local bitwise_ptr_f: BitwiseBuiltin*; if (next_key_nibble == 0) { // Store coordinates of the first item's value. - %{ print(f"\t Branch case, key index = 0") %} + // %{ print(f"\t Branch case, key index = 0") %} assert item_of_interest_start_word = 0; assert item_of_interest_start_offset = first_item_start_offset + 1; assert range_check_ptr_f = range_check_ptr; @@ -478,7 +534,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( } else { if (next_key_nibble == 1) { // Store coordinates of the second item's value. - %{ print(f"\t Branch case, key index = 1") %} + // %{ print(f"\t Branch case, key index = 1") %} let ( second_item_value_start_word, second_item_value_start_offset ) = felt_divmod_8(second_item_value_starts_at_byte); @@ -489,7 +545,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( } else { if (next_key_nibble == 2) { // Store coordinates of the third item's value. - %{ print(f"\t Branch case, key index = 2") %} + // %{ print(f"\t Branch case, key index = 2") %} let ( third_item_value_start_word, third_item_value_start_offset ) = felt_divmod_8(third_item_starts_at_byte + 1); @@ -499,7 +555,7 @@ func decode_node_list_lazy{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( assert bitwise_ptr_f = bitwise_ptr; } else { // Store coordinates of the item's value at index next_key_nibble != (0, 1, 2). - %{ print(f"\t Branch case, key index {ids.next_key_nibble}") %} + // %{ print(f"\t Branch case, key index {ids.next_key_nibble}") %} let (third_item_start_word, third_item_start_offset) = felt_divmod( third_item_starts_at_byte, 8 ); diff --git a/lib/rlp_little.cairo b/lib/rlp_little.cairo index 4a4d3c6..02b182b 100644 --- a/lib/rlp_little.cairo +++ b/lib/rlp_little.cairo @@ -1,7 +1,12 @@ from starkware.cairo.common.cairo_builtins import BitwiseBuiltin from starkware.cairo.common.registers import get_fp_and_pc from starkware.cairo.common.memcpy import memcpy -from starkware.cairo.common.uint256 import Uint256, uint256_pow2, uint256_unsigned_div_rem +from starkware.cairo.common.uint256 import ( + Uint256, + uint256_pow2, + uint256_unsigned_div_rem, + uint256_mul, +) from starkware.cairo.common.alloc import alloc from lib.utils import ( felt_divmod_8, @@ -10,8 +15,141 @@ from lib.utils import ( word_reverse_endian_64, bitwise_divmod, get_felt_bitlength_128, + uint256_reverse_endian_no_padding, + n_bits_to_n_bytes, + get_uint256_bit_length, + get_felt_n_nibbles, + n_bits_to_n_nibbles, + count_trailing_zeroes_128, ) +func n_nibbles_in_key{range_check_ptr}(key: Uint256, pow2_array: felt*) -> (res: felt) { + let (num_bits_in_key) = get_uint256_bit_length(key, pow2_array); + let (num_nibbles_in_key) = n_bits_to_n_nibbles(num_bits_in_key); + return (res=num_nibbles_in_key); +} + +// From a Uint256 number in little endian bytes representation, +// predict the number of leading zeroes nibbles before the number is converted to BE representation. +// Parameters: +// - x: the liitle endian representation of the number. +// - n_nibbles_after_reversion: the fixed # of nibbles in the number after reversion. This is known from RLP decoding. +// - cut_nibble: if 1, takes into account that the leftmost nibble in BE representation will be cut. +// - pow2_array: array of powers of 2. +// Example 1: +// LE input : 0x ab 0d 0f 00 : cut_nibble = 0 +// BE reverted : 0x 00 0f 0d ab -> 3 leading zeroes. +// Example 2: +// LE input : 0x ab 0d 0f e0 : cut_nibble = 1 +// BE reverted: 0x e0 0d 0f ab +// BE reverted + cutted ("e" removed) : 0x 00 d0 fa b -> 2 leading zeroes. +func count_leading_zeroes_from_uint256_le_before_reversion{bitwise_ptr: BitwiseBuiltin*}( + x: Uint256, n_nibbles_after_reversion: felt, cut_nibble: felt, pow2_array: felt* +) -> (res: felt) { + alloc_locals; + %{ + from tools.py.utils import parse_int_to_bytes, count_leading_zero_nibbles_from_hex + input_ = ids.x.low + 2**128*ids.x.high + input_bytes = parse_int_to_bytes(input_) + #print(f"input hex {input_bytes.hex()}") + reversed_bytes = input_bytes[::-1] + #print("reversed bytes", reversed_bytes) + reversed_hex = reversed_bytes.hex() + #print("reversed hex", reversed_hex) + if ids.cut_nibble == 1: + reversed_hex = reversed_hex[1:] + #print(f"Reversed hex final : {reversed_hex}") + expected_leading_zeroes = count_leading_zero_nibbles_from_hex(reversed_hex) + #print(f"Expected leading zeroes {expected_leading_zeroes}") + %} + local x_f: Uint256; + local first_nibble_is_zero; + assert x_f.high = x.high; + if (cut_nibble != 0) { + assert bitwise_ptr.x = x.low; + assert bitwise_ptr.y = 0xffffffffffffffffffffffffffffff0f; + assert bitwise_ptr[1].x = x.low; + assert bitwise_ptr[1].y = 0xf; + let xf_l = bitwise_ptr.x_and_y; + assert x_f.low = xf_l; + let first_nibble = bitwise_ptr[1].x_and_y; + if (first_nibble == 0) { + assert first_nibble_is_zero = 1; + tempvar bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + } else { + assert first_nibble_is_zero = 0; + tempvar bitwise_ptr = bitwise_ptr + 2 * BitwiseBuiltin.SIZE; + } + } else { + assert x_f.low = x.low; + assert bitwise_ptr.x = x.low; + assert bitwise_ptr.y = 0xf0; + let first_nibble = bitwise_ptr.x_and_y / 2 ** 4; + if (first_nibble == 0) { + assert first_nibble_is_zero = 1; + tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + } else { + assert first_nibble_is_zero = 0; + tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + } + } + let (trailing_zeroes_low) = count_trailing_zeroes_128(x_f.low, pow2_array); + if (trailing_zeroes_low == 16) { + // The low part if full of zeroes bytes. + // Need to analyze the high part. + let (trailing_zeroes_high) = count_trailing_zeroes_128(x_f.high, pow2_array); + if (trailing_zeroes_high == 16) { + // The high part is also full of zeroes bytes. + // The number of leading zeroes is then precisely the number of nibbles after reversion. + return (res=n_nibbles_after_reversion); + } else { + // Need to analyse the first nibble after reversion. + let first_non_zero_byte = extract_byte_at_pos( + x_f.high, trailing_zeroes_high, pow2_array + ); + let (first_nibble_after_reversion, _) = bitwise_divmod(first_non_zero_byte, 2 ** 4); + if (first_nibble_after_reversion == 0) { + let res = 32 + 2 * trailing_zeroes_high - cut_nibble + 1; + %{ assert ids.res == expected_leading_zeroes, f"Expected {expected_leading_zeroes} but got {ids.res}" %} + return (res=res); + } else { + let res = 32 + 2 * trailing_zeroes_high - cut_nibble; + %{ assert ids.res == expected_leading_zeroes, f"Expected {expected_leading_zeroes} but got {ids.res}" %} + + return (res=res); + } + } + } else { + // Trailing zeroes bytes between [0, 15]. + if (trailing_zeroes_low == 0) { + let res = first_nibble_is_zero; + %{ assert ids.res == expected_leading_zeroes, f"Expected {expected_leading_zeroes} but got {ids.res}" %} + return (res=res); + } else { + // Trailing zeroes bytes between [1, 15]. + + // Need to check the first nibble after reversion. + let first_non_zero_byte = extract_byte_at_pos(x_f.low, trailing_zeroes_low, pow2_array); + // %{ print(f"{hex(ids.first_non_zero_byte)=}") %} + local first_nibble_after_reversion; + + let (first_nibble_after_reversion, _) = bitwise_divmod(first_non_zero_byte, 2 ** 4); + // %{ print(f"{hex(ids.first_nibble_after_reversion)=}") %} + if (first_nibble_after_reversion == 0) { + let res = 2 * trailing_zeroes_low - cut_nibble + 1; + %{ assert ids.res == expected_leading_zeroes, f"Expected {expected_leading_zeroes} but got {ids.res}" %} + + return (res=res); + } else { + let res = 2 * trailing_zeroes_low - cut_nibble; + %{ assert ids.res == expected_leading_zeroes, f"Expected {expected_leading_zeroes} but got {ids.res}" %} + + return (res=res); + } + } + } +} + // Takes a 64 bit word in little endian, returns the byte at a given position as it would be in big endian. // Ie: word = b7 b6 b5 b4 b3 b2 b1 b0 // returns bi such that i = byte_position @@ -77,181 +215,255 @@ func key_subset_to_uint256(key_subset: felt*, key_subset_len: felt) -> Uint256 { let res = Uint256(low=0, high=0); return res; } -// params: -// key_subset : array of 64 bit words with little endian bytes, representing a subset of the key -// key_subset_len : length of the subset in number of 64 bit words -// key_subset_bytes_len : length of the subset in number of nibbles -// key subset is of the form [b7 b6 b5 b4 b3 b2 b1 b0, b15 b14 b13 b12 b11 b10 b9 b8, ...] -// key_little : 256 bit key in little endian -// key_little is of the form high = [b63, ..., b32] , low = [b31, ..., b0] -// returns the actual number of nibbles checked from key_subset within the actual key_little -func assert_subset_in_key{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + +// Asserts that a subset of the key is in the key in big endian at the correct position given: +// the length of the key subset, the full key, and the nibbles already checked in the full key. +// - key_subset: array of 8 little endian bytes extracted from rlp array. +// - key_subset_len: the length of the key subset (in # of words) +// - key_subset_nibble_len: the number of nibbles in the key subset. Deduced from rlp encoding. +// - key_be: the key to check as a big endian Uint256 number. +// - key_be_nibbles: the number of nibbles in the key (excluding leading zeroes). +// - key_be_leading_zeroes_nibbles: the number of leading zeroes nibbles in the key. +// - n_nibbles_already_checked: the number of nibbles already checked in the key. +// - cut_nibble: 1 if the first nibble from the extracted key needs to be cut. 0 otherwise. +// - pow2_array: array of powers of 2. +// Ex : Full Key is 0x012345678 +// Nibbles checked is 2 +// Key subset is 0x4523 (little endian) +// First key subset is going to be reversed to big endian : 0x2345 +// Then Full Key will first be cutted to 0x2345678 (n_nibbles checked removed on the left) +// Then again cutted to 0x2345 (keep key_subset_nibble_len on the left) +// Then the key subset will be asserted against the cutted key. +func assert_subset_in_key_be{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( key_subset: felt*, key_subset_len: felt, key_subset_nibble_len: felt, - key_little: Uint256, + key_be: Uint256, + key_be_nibbles: felt, + key_be_leading_zeroes_nibbles: felt, n_nibbles_already_checked: felt, cut_nibble: felt, pow2_array: felt*, -) -> (n_nibbles_checked: felt) { +) { alloc_locals; - let key_subset_256t = key_subset_to_uint256(key_subset, key_subset_len); - %{ print(f"key_susbet_uncut={hex(ids.key_subset_256t.low + ids.key_subset_256t.high*2**128)}") %} - local key_subset_256: Uint256; - local key_subset_last_nibble: felt; - - let (_, odd_checked_nibbles) = felt_divmod(n_nibbles_already_checked, 2); + // Get the little endian 256 bit number from the extracted 64 bit le words array : + let key_subset_256_le = key_subset_to_uint256(key_subset, key_subset_len); + %{ + key_subset_256_le = hex(ids.key_subset_256_le.low + ids.key_subset_256_le.high*2**128)[2:] + print(f"Key subset 256 le: {key_subset_256_le}") + %} + let (key_subset_be_tmp: Uint256, n_bytes: felt) = uint256_reverse_endian_no_padding( + key_subset_256_le, pow2_array + ); + %{ + orig_key = hex(ids.key_be.low + ids.key_be.high*2**128)[2:] + key_subset = hex(ids.key_subset_be_tmp.low + ids.key_subset_be_tmp.high*2**128)[2:] + print(f"Orig key: {orig_key}, n_nibbles={len(orig_key)}") + print(f"Key subset: {key_subset}, n_nibbles={len(key_subset)}") + %} + // Cut nibble of the key subset if needed from the leftmost position. 0x123 -> 0x23 + local key_subset_be: Uint256; + local bitwise_ptr_f: BitwiseBuiltin*; if (cut_nibble != 0) { %{ print(f"Cut nibble") %} - let (key_subset_256ltmp, byte) = felt_divmod(key_subset_256t.low, 2 ** 8); - let (key_subset_256h, acc) = felt_divmod(key_subset_256t.high, 2 ** 8); - let (_, nibble) = felt_divmod(byte, 2 ** 4); - assert key_subset_256.low = key_subset_256ltmp + acc * 2 ** (128 - 8); - assert key_subset_256.high = key_subset_256h; - assert key_subset_last_nibble = nibble; - tempvar range_check_ptr = range_check_ptr; - } else { - assert key_subset_256.low = key_subset_256t.low; - assert key_subset_256.high = key_subset_256t.high; - assert key_subset_last_nibble = 0; - tempvar range_check_ptr = range_check_ptr; - } - %{ print(f"key_susbet_cutted={hex(ids.key_subset_256.low + ids.key_subset_256.high*2**128)}") %} - %{ print(f"key_little={hex(ids.key_little.low + ids.key_little.high*2**128)}") %} - - local key_shifted: Uint256; - local key_shifted_last_nibble: felt; - if (odd_checked_nibbles != 0) { - let (upow) = uint256_pow2(Uint256((n_nibbles_already_checked + 1) * 4, 0)); // p = 2**(n_nib_checked+1) - let (key_shiftedt, rem) = uint256_unsigned_div_rem(key_little, upow); // - let (upow_) = uint256_pow2(Uint256((n_nibbles_already_checked - 1) * 4, 0)); - let (byte_u256, _) = uint256_unsigned_div_rem(rem, upow_); - let (_, nibble) = felt_divmod(byte_u256.low, 2 ** 4); - assert key_shifted.low = key_shiftedt.low; - assert key_shifted.high = key_shiftedt.high; - assert key_shifted_last_nibble = nibble; - tempvar range_check_ptr = range_check_ptr; + if (key_subset_be_tmp.high != 0) { + let (_, key_susbet_be_high) = bitwise_divmod( + key_subset_be_tmp.high, pow2_array[8 * (n_bytes - 16) - 4] + ); + assert key_subset_be.low = key_subset_be_tmp.low; + assert key_subset_be.high = key_susbet_be_high; + assert bitwise_ptr_f = bitwise_ptr; + } else { + let (_, key_susbet_be_low) = bitwise_divmod( + key_subset_be_tmp.low, pow2_array[8 * n_bytes - 4] + ); + assert key_subset_be.low = key_susbet_be_low; + assert key_subset_be.high = 0; + assert bitwise_ptr_f = bitwise_ptr; + } } else { - let (upow) = uint256_pow2(Uint256(n_nibbles_already_checked * 4, 0)); - let (key_shiftedt, _) = uint256_unsigned_div_rem(key_little, upow); - assert key_shifted.low = key_shiftedt.low; - assert key_shifted.high = key_shiftedt.high; - assert key_shifted_last_nibble = 0; - tempvar range_check_ptr = range_check_ptr; + assert key_subset_be.low = key_subset_be_tmp.low; + assert key_subset_be.high = key_subset_be_tmp.high; + assert bitwise_ptr_f = bitwise_ptr; } - - %{ print(f"key_shifted={hex(ids.key_shifted.low + ids.key_shifted.high*2**128)}") %} - - if (key_subset_256.high != 0) { - // caution : high part must have less or equal 30 nibbles. for felt divmod. - let n_nibble_in_high_part = key_subset_nibble_len - 32; - let (_, key_high) = bitwise_divmod{bitwise_ptr=bitwise_ptr}( - key_shifted.high, pow2_array[4 * n_nibble_in_high_part] + let bitwise_ptr = bitwise_ptr_f; + // %{ + // key_subset_cut = hex(ids.key_subset_be.low + ids.key_subset_be.high*2**128)[2:] + // print(f"Key subset cut: {key_subset_cut}, n_nibbles={len(key_subset_cut)}") + // %} + local bitwise_ptr_f: BitwiseBuiltin*; + local range_check_ptr_f; + local key_subset_be_final: Uint256; + let (key_subset_bits) = get_uint256_bit_length(key_subset_be, pow2_array); + let (key_subset_nibbles) = n_bits_to_n_nibbles(key_subset_bits); + + // Remove n_nibbles_already_checked nibbles from the left part of the key + // %{ print(f"Remove {ids.n_nibbles_already_checked} nibbles from the left part of the key") %} + let (u256_power) = uint256_pow2( + Uint256((key_be_nibbles + key_be_leading_zeroes_nibbles - n_nibbles_already_checked) * 4, 0) + ); + let (_, key_shifted) = uint256_unsigned_div_rem(key_be, u256_power); + // %{ print(f"Key shifted: {hex(ids.key_shifted.low + ids.key_shifted.high*2**128)}") %} + + // Remove rightmost part of the key, keep only key_subset_nibble_len nibbles on the left + // %{ + // print(f"Remove rightmost part of the key, keep only {ids.key_subset_nibble_len} nibbles on the left") + // power = ids.key_be_nibbles + ids.key_be_leading_zeroes_nibbles - ids.n_nibbles_already_checked - ids.key_subset_nibble_len + // print(f"Computing 2**({power}) = {power/4} nibbles = {power/8} bytes") + // %} + let (u256_power) = uint256_pow2( + Uint256( + 4 * ( + key_be_nibbles + + key_be_leading_zeroes_nibbles - + n_nibbles_already_checked - + key_subset_nibble_len + ), + 0, + ), + ); + let (key_shifted, _) = uint256_unsigned_div_rem(key_shifted, u256_power); + // %{ print(f"Key shifted final: {hex(ids.key_shifted.low + ids.key_shifted.high*2**128)}") %} + + if (key_subset_nibbles != key_subset_nibble_len) { + // Nibbles lens don't match. + // %{ print(f"Nibbles lens don't match: {ids.key_subset_nibbles=} != {ids.key_subset_nibble_len=}") %} + // This either come from : + // 1. the leftmost nibbles of the BE key (right most nibbles of the LE key) being 0's + // 2. the the rightmost nibbles of the BE key being 0's. + + // Handle 1. : count leftfmost nibbles of the BE key from the rightmost nibbles of the LE key: + let (n_leading_zeroes_nibbles) = count_leading_zeroes_from_uint256_le_before_reversion( + key_subset_256_le, key_subset_nibble_len, cut_nibble, pow2_array ); - - %{ - print(f"\t N nibbles in right part : {ids.n_nibble_in_high_part}") - print(f"\t orig key high : {hex(ids.key_little.high)}") - print(f"\t key shifted high : {hex(ids.key_shifted.high)}") - print(f"\t final key high : {hex(ids.key_high)}") - print(f"\t key subset high : {hex(ids.key_subset_256.high)}") - %} - local key_subset_nibbles; - let key_subset_bits = get_felt_bitlength_128{pow2_array=pow2_array}(key_subset_256.high); - let (key_subset_nibbles_tmp, remainder) = felt_divmod(128 + key_subset_bits, 4); - if (remainder != 0) { - assert key_subset_nibbles = key_subset_nibbles_tmp + 1; + // %{ print(f"n_leading_zeroes_nibbles: {ids.n_leading_zeroes_nibbles}") %} + if (key_subset_nibble_len - (key_subset_nibbles + n_leading_zeroes_nibbles) != 0) { + // Handle 2. : Right pad the BE key with 0's until the expected length. + // %{ print(f"Right pad with {ids.key_subset_nibble_len - (ids.key_subset_nibbles + ids.n_leading_zeroes_nibbles)} 0's") %} + let (u256_pow) = uint256_pow2( + Uint256( + (key_subset_nibble_len - (key_subset_nibbles + n_leading_zeroes_nibbles)) * 4, 0 + ), + ); + let (res_tmp, _) = uint256_mul(key_subset_be, u256_pow); + assert key_subset_be_final.low = res_tmp.low; + assert key_subset_be_final.high = res_tmp.high; + assert range_check_ptr_f = range_check_ptr; + assert bitwise_ptr_f = bitwise_ptr; } else { - assert key_subset_nibbles = key_subset_nibbles_tmp; + // %{ print(f"Do nothing. Nibble lens including leading zeroes match") %} + // Handle 1. Nothing to do. Nibble lens including leading zeroes match. + assert key_subset_be_final.low = key_subset_be.low; + assert key_subset_be_final.high = key_subset_be.high; + assert range_check_ptr_f = range_check_ptr; + assert bitwise_ptr_f = bitwise_ptr; } - assert key_subset_256.low = key_shifted.low; - assert key_subset_256.high = key_high; - assert key_subset_last_nibble = key_shifted_last_nibble; - return (n_nibbles_checked=key_subset_nibbles + cut_nibble); } else { - let (_, key_low) = felt_divmod(key_shifted.low, pow2_array[4 * key_subset_nibble_len]); - assert key_subset_256.low = key_low; - assert key_subset_256.high = 0; - assert key_subset_last_nibble = key_shifted_last_nibble; - local key_subset_nibbles; - let key_subset_bits = get_felt_bitlength_128{pow2_array=pow2_array}(key_subset_256.low); - let (key_subset_nibbles_tmp, remainder) = felt_divmod(key_subset_bits, 4); - - if (remainder != 0) { - assert key_subset_nibbles = key_subset_nibbles_tmp + 1; - } else { - assert key_subset_nibbles = key_subset_nibbles_tmp; - } - - return (n_nibbles_checked=key_subset_nibbles + cut_nibble); + // %{ print(f"Do nothing. Nibble lens match") %} + // Do nothing if the nibble lens already match. Assertions will pass. + assert key_subset_be_final.low = key_subset_be.low; + assert key_subset_be_final.high = key_subset_be.high; + assert range_check_ptr_f = range_check_ptr; + assert bitwise_ptr_f = bitwise_ptr; } + let bitwise_ptr = bitwise_ptr_f; + let range_check_ptr = range_check_ptr_f; + // %{ print(f"Key subset final: {hex(ids.key_subset_be_final.low + ids.key_subset_be_final.high*2**128)}") %} + + // %{ print(f"key subset expect: {hex(ids.key_shifted.low + ids.key_shifted.high*2**128)}") %} + assert key_subset_be_final.low = key_shifted.low; + assert key_subset_be_final.high = key_shifted.high; + return (); } -// From a key with reverse little endian bytes of the form : -// key = n62 n63 n60 n61 n58 n59 n56 n57 n54 n55 n52 n53 n50 n51 n48 n49 n46 n47 n44 n45 n42 n43 n40 n41 n38 n39 n36 n37 n34 n35 n32 n33 n30 n31 n28 n29 n26 n27 n24 n25 n22 n23 n20 n21 n18 n19 n16 n17 n14 n15 n12 n13 n10 n11 n8 n9 n6 n7 n4 n5 n2 n3 n0 n1 +// From a 256 bit key in big endian of the form : +// key = n0 n1 n2 ... n62 n63 // returns ni such that i = nibble_index -// Since key is assumed to be in little endian, nibble index is ordered to start from the most significant nibble for the big endian representation, -// ie : nibble_index = 0 => most significant nibble of key in big endian -func extract_nibble_from_key{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( - key: Uint256, nibble_index: felt, pow2_array: felt* +// Params: +// key: the Uint256 number representing the key in big endian +// key_nibbles: the number of nibbles in the key (excluding leading zeroes) +// key_leading_zeroes_nibbles: the number of leading zeroes nibbles in the key +// nibble_index: the index of the nibble to extract +// pow2_array: array of powers of 2 +func extract_nibble_from_key_be{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + key: Uint256, + key_nibbles: felt, + key_leading_zeroes_nibbles: felt, + nibble_index: felt, + pow2_array: felt*, ) -> felt { alloc_locals; - local get_nibble_from_low: felt; - local nibble_pos: felt; - %{ - ids.get_nibble_from_low = 1 if 0 <= ids.nibble_index <= 31 else 0 - ids.nibble_pos = ids.nibble_index % 2 - %} - %{ - print(f"Key low: {hex(ids.key.low)}") - print(f"Key high: {hex(ids.key.high)}") - print(f"nibble_index: {ids.nibble_index}") - %} - if (get_nibble_from_low != 0) { - if (nibble_pos != 0) { - %{ print(f"\t case 0 ") %} - assert [range_check_ptr] = 31 - nibble_index; - assert bitwise_ptr.x = key.low; - assert bitwise_ptr.y = 0xf * pow2_array[4 * (nibble_index - 1)]; - let extracted_nibble_at_pos = bitwise_ptr.x_and_y / pow2_array[4 * (nibble_index - 1)]; + local is_zero; + %{ ids.is_zero = 1 if ids.nibble_index <= (ids.key_leading_zeroes_nibbles - 1) else 0 %} + if (is_zero != 0) { + // %{ print(f"\t {ids.nibble_index} <= {ids.key_leading_zeroes_nibbles - 1}") %} + // nibble_index is in [0, key_leading_zeroes_nibbles - 1] + assert [range_check_ptr] = (key_leading_zeroes_nibbles - 1) - nibble_index; + tempvar range_check_ptr = range_check_ptr + 1; + return 0; + } else { + // %{ print(f"\t {ids.nibble_index} > {ids.key_leading_zeroes_nibbles - 1}") %} + // nibble_index is >= key_leading_zeroes_nibbles + assert [range_check_ptr] = nibble_index - key_leading_zeroes_nibbles; + tempvar range_check_ptr = range_check_ptr + 1; + // Reindex nibble_index to start from 0 accounting for the leading zeroes + // Ex: key is 0x00abc. Nibble index is 2 (=> nibble is "a"). Reindexed nibble index is then 2-2=0. + let nibble_index = nibble_index - key_leading_zeroes_nibbles; + local get_nibble_from_low: felt; + // we get the nibble from low part of key either if : + // - nibble_index is in [0, 31] and key_nibbles <= 32 + // - nibble_index is in [32, 63] and key_nibbles > 32 + // Consenquently, we get the nibble from high part of the key only if : + // - nibble_index is in [0, 31] and key_nibbles > 32 + %{ ids.get_nibble_from_low = 1 if (0 <= ids.nibble_index <= 31 and ids.key_nibbles <= 32) or (32 <= ids.nibble_index <= 63 and ids.key_nibbles > 32) else 0 %} + if (key.high != 0) { + // key_nibbles > 32 + } + %{ + #print(f"Key low: {hex(ids.key.low)}") + #print(f"Key high: {hex(ids.key.high)}") + #print(f"nibble_index: {ids.nibble_index}") + #print(f"key_nibbles: {ids.key_nibbles}") + #print(f"key_leading_zeroes_nibbles: {ids.key_leading_zeroes_nibbles}") + key_hex = ids.key_leading_zeroes_nibbles*'0'+hex(ids.key.low + 2**128*ids.key.high)[2:] + #print(f"Key hex: {key_hex}") + expected_nibble = int(key_hex[ids.nibble_index+ids.key_leading_zeroes_nibbles], 16) + %} + if (get_nibble_from_low != 0) { + local offset; + if (key.high != 0) { + // key_nibbles > 32. Then nibble_index must be in [32, 63] + assert [range_check_ptr] = 31 - (nibble_index - 32); + assert offset = pow2_array[4 * (32 - nibble_index - 1)]; + } else { + // key_nibbles <= 32. Then nibble_index must be in [0, 31] + assert [range_check_ptr] = 31 - nibble_index; + assert offset = pow2_array[4 * (key_nibbles - nibble_index - 1)]; + } tempvar range_check_ptr = range_check_ptr + 1; - tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; - return extracted_nibble_at_pos; - } else { - %{ print(f"\t case 1 ") %} - - assert [range_check_ptr] = 31 - nibble_index; assert bitwise_ptr.x = key.low; - assert bitwise_ptr.y = 0xf * pow2_array[4 * nibble_index + 4]; - let extracted_nibble_at_pos = bitwise_ptr.x_and_y / pow2_array[4 * nibble_index + 4]; - tempvar range_check_ptr = range_check_ptr + 1; - tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; - return extracted_nibble_at_pos; - } - } else { - if (nibble_pos != 0) { - %{ print(f"\t case 2 ") %} - - assert [range_check_ptr] = 31 - (nibble_index - 32); - tempvar offset = pow2_array[4 * (nibble_index - 32)]; - assert bitwise_ptr.x = key.high; assert bitwise_ptr.y = 0xf * offset; - let extracted_nibble_at_pos = bitwise_ptr.x_and_y / offset; - tempvar range_check_ptr = range_check_ptr + 1; + tempvar extracted_nibble_at_pos = bitwise_ptr.x_and_y / offset; tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + %{ assert ids.extracted_nibble_at_pos == expected_nibble, f"extracted_nibble_at_pos={ids.extracted_nibble_at_pos} expected_nibble={expected_nibble}" %} return extracted_nibble_at_pos; } else { - %{ print(f"\t case 3 ") %} - - assert [range_check_ptr] = 31 - (nibble_index - 32); - tempvar offset = pow2_array[4 * (nibble_index - 32) + 4]; + // Extract nibble from high part of key + // nibble index must be in [0, 31] and key_nibbles > 32 + assert [range_check_ptr] = 31 - nibble_index; + if (key.high == 0) { + assert 1 = 0; + } + tempvar offset = pow2_array[4 * (key_nibbles - 32 - nibble_index - 1)]; assert bitwise_ptr.x = key.high; assert bitwise_ptr.y = 0xf * offset; - let extracted_nibble_at_pos = bitwise_ptr.x_and_y / offset; + tempvar extracted_nibble_at_pos = bitwise_ptr.x_and_y / offset; tempvar range_check_ptr = range_check_ptr + 1; tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + %{ assert ids.extracted_nibble_at_pos == expected_nibble, f"extracted_nibble_at_pos={ids.extracted_nibble_at_pos} expected_nibble={expected_nibble}" %} + return extracted_nibble_at_pos; } } @@ -265,13 +477,13 @@ func extract_nibble_from_key{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( func extract_n_bytes_at_pos{bitwise_ptr: BitwiseBuiltin*}( word_64_little: felt, pos: felt, n: felt, pow2_array: felt* ) -> felt { - %{ print(f"extracting {ids.n} bytes at pos {ids.pos} from {hex(ids.word_64_little)}") %} + // %{ print(f"extracting {ids.n} bytes at pos {ids.pos} from {hex(ids.word_64_little)}") %} let x_mask = get_0xff_mask(n); - %{ print(f"x_mask for len {ids.n}: {hex(ids.x_mask)}") %} + // %{ print(f"x_mask for len {ids.n}: {hex(ids.x_mask)}") %} assert bitwise_ptr[0].x = word_64_little; assert bitwise_ptr[0].y = x_mask * pow2_array[8 * (pos)]; tempvar res = bitwise_ptr[0].x_and_y; - %{ print(f"tmp : {hex(ids.res)}") %} + // %{ print(f"tmp : {hex(ids.res)}") %} tempvar extracted_bytes = bitwise_ptr[0].x_and_y / pow2_array[8 * pos]; tempvar bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; return extracted_bytes; @@ -447,8 +659,6 @@ func extract_n_bytes_from_le_64_chunks_array{range_check_ptr}( return (res, n_words_handled); } -// func extract_n_bytes_from_le_64_chunks_array_inner(array:felt*, current_word:felt, n_words_handled:felt, - func array_copy(src: felt*, dst: felt*, n: felt, index: felt) { if (index == n) { return (); diff --git a/lib/utils.cairo b/lib/utils.cairo index 275b6d5..a7b831e 100644 --- a/lib/utils.cairo +++ b/lib/utils.cairo @@ -15,6 +15,174 @@ from starkware.cairo.common.registers import get_fp_and_pc const DIV_32 = 2 ** 32; const DIV_32_MINUS_1 = DIV_32 - 1; +// Takes the hex representation and count the number of zeroes. +// Ie: returns the number of trailing zeroes bytes. +// If x is 0, returns 16. +func count_trailing_zeroes_128{bitwise_ptr: BitwiseBuiltin*}(x: felt, pow2_array: felt*) -> ( + res: felt +) { + if (x == 0) { + return (res=16); + } + alloc_locals; + local trailing_zeroes_bytes; + %{ + from tools.py.utils import count_trailing_zero_bytes_from_int + ids.trailing_zeroes_bytes = count_trailing_zero_bytes_from_int(ids.x) + #print(f"Input: {hex(ids.x)}_{ids.trailing_zeroes_bytes}Tr_Zerobytes") + %} + // Verify. + if (trailing_zeroes_bytes == 0) { + // Make sure the last byte is not zero. + let (_, last_byte) = bitwise_divmod(x, 2 ** 8); + if (last_byte == 0) { + assert 1 = 0; // Add unsatisfiability check. + return (res=0); + } else { + return (res=0); + } + } else { + // Make sure the last trailing_zeroes_bytes are zeroes. + let (q, r) = bitwise_divmod(x, pow2_array[8 * trailing_zeroes_bytes]); + assert r = 0; + // Make sure the byte just before the last trailing_zeroes_bytes is not zero. + let (_, first_non_zero_byte) = bitwise_divmod(q, 2 ** 8); + if (first_non_zero_byte == 0) { + assert 1 = 0; // Add unsatisfiability check. + return (res=0); + } else { + return (res=trailing_zeroes_bytes); + } + } +} + +// Returns the number of bytes in a number with n_bits bits. +// Assumptions: +// - 0 <= n_bits < 8 * RC_BOUND +func n_bits_to_n_bytes{range_check_ptr: felt}(n_bits: felt) -> (res: felt) { + if (n_bits == 0) { + return (res=0); + } + let (q, r) = felt_divmod_8(n_bits); + if (q == 0) { + return (res=1); + } + if (r == 0) { + return (res=q); + } + return (res=q + 1); +} + +// Returns the number of nibbles in a number with n_bits bits. +// Assumptions: +// - 0 <= n_bits < 4 * RC_BOUND +func n_bits_to_n_nibbles{range_check_ptr: felt}(n_bits: felt) -> (res: felt) { + if (n_bits == 0) { + return (res=0); + } + let (q, r) = felt_divmod(n_bits, 4); + if (q == 0) { + return (res=1); + } + if (r == 0) { + return (res=q); + } + return (res=q + 1); +} + +// Returns the number of bytes in a 128 bits number. +// Assumptions: +// - 0 <= x < 2^128 +func get_felt_n_bytes_128{range_check_ptr: felt}(x: felt, pow2_array: felt*) -> (n_bytes: felt) { + let n_bits = get_felt_bitlength_128{pow2_array=pow2_array}(x); + let (n_bytes) = n_bits_to_n_bytes(n_bits); + return (n_bytes,); +} + +// Returns the number of nibbles in a 128 bits number. +func get_felt_n_nibbles{range_check_ptr: felt}(x: felt, pow2_array: felt*) -> (n_nibbles: felt) { + let n_bits = get_felt_bitlength_128{pow2_array=pow2_array}(x); + let (n_nibbles) = n_bits_to_n_nibbles(n_bits); + return (n_nibbles,); +} +// Returns the total number of bits in the uint256 number. +// Assumptions : +// - 0 <= x < 2^256 +// Returns: +// - nbits: felt - Total number of bits in the uint256 number. +func get_uint256_bit_length{range_check_ptr}(x: Uint256, pow2_array: felt*) -> (nbits: felt) { + alloc_locals; + with pow2_array { + if (x.high != 0) { + let x_bit_high = get_felt_bitlength_128(x.high); + return (nbits=128 + x_bit_high); + } else { + if (x.low != 0) { + let x_bit_low = get_felt_bitlength_128(x.low); + return (nbits=x_bit_low); + } else { + return (nbits=0); + } + } + } +} + +// Takes a uint128 number, reverse its byte endianness without adding right-padding +// Ex : +// Input = 0x123456 +// Output = 0x563412 +// Input = 0x123 +// Output = 0x0312 +func uint128_reverse_endian_no_padding{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + x: felt, pow2_array: felt* +) -> (res: felt, n_bytes: felt) { + alloc_locals; + let (num_bytes_input) = get_felt_n_bytes_128(x, pow2_array); + let (x_reversed) = word_reverse_endian(x); + let (num_bytes_reversed) = get_felt_n_bytes_128(x_reversed, pow2_array); + let (trailing_zeroes_input) = count_trailing_zeroes_128(x, pow2_array); + + if (num_bytes_input != num_bytes_reversed) { + // %{ print(f"\tinput128: {hex(ids.x)}_{ids.num_bytes_input}bytes") %} + // %{ print(f"\treversed: {hex(ids.x_reversed)}_{ids.num_bytes_reversed}bytes") %} + let (x_reversed, r) = bitwise_divmod( + x_reversed, + pow2_array[8 * (num_bytes_reversed - num_bytes_input + trailing_zeroes_input)], + ); + assert r = 0; // Sanity check. + // %{ + // import math + // print(f"\treversed_fixed: {hex(ids.x_reversed)}_{math.ceil(ids.x_reversed.bit_length() / 8)}bytes") + // %} + return (res=x_reversed, n_bytes=num_bytes_input); + } + return (res=x_reversed, n_bytes=num_bytes_input); +} + +// Takes a uint256 number, reverse its byte endianness without adding right-padding and returns the number of bytes. +func uint256_reverse_endian_no_padding{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + x: Uint256, pow2_array: felt* +) -> (res: Uint256, n_bytes: felt) { + alloc_locals; + if (x.high != 0) { + let (high_reversed, n_bytes_high) = uint128_reverse_endian_no_padding(x.high, pow2_array); + // %{ print(f"High_Rev: {hex(ids.high_reversed)}_{ids.high_reversed.bit_length()}b {ids.n_bytes_high}bytes") %} + let (low_reversed) = word_reverse_endian(x.low); + // %{ print(f"Low_rev: {hex(ids.low_reversed)}_{ids.low_reversed.bit_length()}b") %} + + let (q, r) = bitwise_divmod(low_reversed, pow2_array[8 * (16 - n_bytes_high)]); + // %{ print(f"Q: {hex(ids.q)}") %} + // %{ print(f"R: {hex(ids.r)}") %} + return ( + res=Uint256(low=high_reversed + pow2_array[8 * n_bytes_high] * r, high=q), + n_bytes=16 + n_bytes_high, + ); + } else { + let (low_reversed, n_bytes_low) = uint128_reverse_endian_no_padding(x.low, pow2_array); + return (res=Uint256(low=low_reversed, high=0), n_bytes=n_bytes_low); + } +} + // Adds two integers. Returns the result as a 256-bit integer and the (1-bit) carry. // Strictly equivalent and faster version of common.uint256.uint256_add using the same whitelisted hint. func uint256_add{range_check_ptr}(a: Uint256, b: Uint256) -> (res: Uint256, carry: felt) { @@ -126,10 +294,13 @@ func write_felt_array_to_dict_keys{dict_end: DictAccess*}(array: felt*, index: f // Params: // - x: felt - Input value. // Assumptions for the caller: -// - 1 <= x < 2^127 +// - 0 <= x < 2^127 // Returns: // - bit_length: felt - Number of bits in x. func get_felt_bitlength{range_check_ptr, pow2_array: felt*}(x: felt) -> felt { + if (x == 0) { + return 0; + } alloc_locals; local bit_length; %{ @@ -154,12 +325,16 @@ func get_felt_bitlength{range_check_ptr, pow2_array: felt*}(x: felt) -> felt { // Params: // - x: felt - Input value. // Assumptions for the caller: -// - 1 <= x < 2^128 +// - 0 <= x < 2^128 // Returns: // - bit_length: felt - Number of bits in x. func get_felt_bitlength_128{range_check_ptr, pow2_array: felt*}(x: felt) -> felt { + if (x == 0) { + return 0; + } alloc_locals; local bit_length; + %{ x = ids.x ids.bit_length = x.bit_length() @@ -191,12 +366,17 @@ func get_felt_bitlength_128{range_check_ptr, pow2_array: felt*}(x: felt) -> felt // q: the quotient. // r: the remainder. func bitwise_divmod{bitwise_ptr: BitwiseBuiltin*}(x: felt, y: felt) -> (q: felt, r: felt) { - assert bitwise_ptr.x = x; - assert bitwise_ptr.y = y - 1; - let x_and_y = bitwise_ptr.x_and_y; + if (y == 1) { + let bitwise_ptr = bitwise_ptr; + return (q=x, r=0); + } else { + assert bitwise_ptr.x = x; + assert bitwise_ptr.y = y - 1; + let x_and_y = bitwise_ptr.x_and_y; - let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; - return (q=(x - x_and_y) / y, r=x_and_y); + let bitwise_ptr = bitwise_ptr + BitwiseBuiltin.SIZE; + return (q=(x - x_and_y) / y, r=x_and_y); + } } // Computes x//(2**32) and x%(2**32) using range checks operations. diff --git a/tests/cairo_programs/mpt_prove_EOA_test.cairo b/tests/cairo_programs/mpt_prove_EOA_test.cairo index 11d828a..993da2b 100644 --- a/tests/cairo_programs/mpt_prove_EOA_test.cairo +++ b/tests/cairo_programs/mpt_prove_EOA_test.cairo @@ -75,13 +75,10 @@ func main{ %} let (pow2_array: felt*) = pow2alloc127(); - let (keys_little: Uint256*) = alloc(); + let (keys_be: Uint256*) = alloc(); hash_n_addresses( - addresses_64_little=addresses_64_little, - keys_little=keys_little, - n_addresses=n_proofs, - index=0, + addresses_64_little=addresses_64_little, keys_be=keys_be, n_addresses=n_proofs, index=0 ); let (values: felt**) = alloc(); @@ -91,7 +88,7 @@ func main{ mpt_proofs=account_proofs, mpt_proofs_bytes_len=account_proofs_bytes_len, mpt_proofs_len=account_proofs_len, - keys_little=keys_little, + keys_be=keys_be, hashes_to_assert=state_roots, n_proofs=n_proofs, index=0, @@ -104,19 +101,20 @@ func main{ } func hash_n_addresses{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: KeccakBuiltin*}( - addresses_64_little: felt**, keys_little: Uint256*, n_addresses: felt, index: felt + addresses_64_little: felt**, keys_be: Uint256*, n_addresses: felt, index: felt ) { alloc_locals; if (index == n_addresses) { return (); } else { - let (hash: Uint256) = keccak(addresses_64_little[index], 20); - assert keys_little[index].low = hash.low; - assert keys_little[index].high = hash.high; + let (hash_le: Uint256) = keccak(addresses_64_little[index], 20); + let (hash: Uint256) = uint256_reverse_endian(hash_le); + assert keys_be[index].low = hash.low; + assert keys_be[index].high = hash.high; return hash_n_addresses( addresses_64_little=addresses_64_little, - keys_little=keys_little, + keys_be=keys_be, n_addresses=n_addresses, index=index + 1, ); @@ -127,7 +125,7 @@ func verify_n_mpt_proofs{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_p mpt_proofs: felt***, mpt_proofs_bytes_len: felt**, mpt_proofs_len: felt*, - keys_little: Uint256*, + keys_be: Uint256*, hashes_to_assert: Uint256*, n_proofs: felt, index: felt, @@ -139,14 +137,19 @@ func verify_n_mpt_proofs{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_p if (index == n_proofs) { return (values=values, values_lens=values_lens); } else { + local key_be_leading_zeroes_nibbles; + let key_be: Uint256 = keys_be[index]; + %{ + from tools.py.utils import count_leading_zero_nibbles_from_hex + ids.key_be_leading_zeroes_nibbles = count_leading_zero_nibbles_from_hex(hex(ids.key_be.low+2**128*ids.key_be.high)) + %} let (value: felt*, value_len: felt) = verify_mpt_proof( mpt_proof=mpt_proofs[index], mpt_proof_bytes_len=mpt_proofs_bytes_len[index], mpt_proof_len=mpt_proofs_len[index], - key_little=keys_little[index], - n_nibbles_already_checked=0, - node_index=0, - hash_to_assert=hashes_to_assert[index], + key_be=key_be, + key_be_leading_zeroes_nibbles=key_be_leading_zeroes_nibbles, + root=hashes_to_assert[index], pow2_array=pow2_array, ); assert values_lens[index] = value_len; @@ -155,7 +158,7 @@ func verify_n_mpt_proofs{range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_p mpt_proofs=mpt_proofs, mpt_proofs_bytes_len=mpt_proofs_bytes_len, mpt_proofs_len=mpt_proofs_len, - keys_little=keys_little, + keys_be=keys_be, hashes_to_assert=hashes_to_assert, n_proofs=n_proofs, index=index + 1, diff --git a/tests/cairo_programs/reverse_uint256.cairo b/tests/cairo_programs/reverse_uint256.cairo new file mode 100644 index 0000000..c1ccd16 --- /dev/null +++ b/tests/cairo_programs/reverse_uint256.cairo @@ -0,0 +1,109 @@ +%builtins output range_check bitwise + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin + +from lib.utils import pow2alloc128, uint256_reverse_endian_no_padding, Uint256 + +func main{output_ptr: felt*, range_check_ptr, bitwise_ptr: BitwiseBuiltin*}() { + alloc_locals; + let (pow2_array: felt*) = pow2alloc128(); + + // Some edge cases. + local x1: Uint256; + local x2: Uint256; + local x3: Uint256; + local x4: Uint256; + local x5: Uint256; + local x6: Uint256; + local x7: Uint256; + %{ + import random + random.seed(0) + from tools.py.utils import split_128, parse_int_to_bytes, count_leading_zero_nibbles_from_hex + + x1 = 0x5553adf1a587bc5465b321660008c4c2e825bd3df2d2ccf001a009f3 + x2 = 0xb847b60dcb5d984fc2a1ca0040a550cd3c4ac0adef268ded1249e1ae + x3 = 0xd4ae28bf208da8ad396463110021760d8278befbac8b4ecacb7c6e00 + x4 = 0x12345600 + x5 = 0x12401 + x6 = 0x1240100 + x7 = 0x124010 + + ids.x1.low, ids.x1.high = split_128(x1) + ids.x2.low, ids.x2.high = split_128(x2) + ids.x3.low, ids.x3.high = split_128(x3) + ids.x4.low, ids.x4.high = split_128(x4) + ids.x5.low, ids.x5.high = split_128(x5) + ids.x6.low, ids.x6.high = split_128(x6) + ids.x7.low, ids.x7.high = split_128(x7) + + def test_function(test_input:int, test_output:int): + input_bytes = parse_int_to_bytes(test_input) + res_bytes = parse_int_to_bytes(test_output) + + print(f"test_input: {input_bytes}") + print(f"test_output: {res_bytes}") + + expected_output = input_bytes[::-1] # Reverse the input bytes. + # Trim leading zeroes from expected output : + expected_output = expected_output.lstrip(b'\x00') + # The input and output bytes should be the same, reversed. + assert expected_output == res_bytes, f"{expected_output} != {res_bytes}" + %} + + test_reverse_single(x=x1, pow2_array=pow2_array); + test_reverse_single(x=x2, pow2_array=pow2_array); + test_reverse_single(x=x3, pow2_array=pow2_array); + test_reverse_single(x=x4, pow2_array=pow2_array); + test_reverse_single(x=x5, pow2_array=pow2_array); + test_reverse_single(x=x6, pow2_array=pow2_array); + test_reverse_single(x=x7, pow2_array=pow2_array); + + test_reverse(n_bits_index=1, pow2_array=pow2_array); + + %{ print("End tests!") %} + + return (); +} + +func test_reverse_single{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + x: Uint256, pow2_array: felt* +) { + alloc_locals; + let (res, n_bytes) = uint256_reverse_endian_no_padding(x, pow2_array); + %{ + # Test. + test_function(test_input=ids.x.low + 2**128*ids.x.high, test_output=ids.res.low+2**128*ids.res.high) + %} + return (); +} +func test_reverse_inner{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + n_bits_in_input: felt, pow2_array: felt* +) { + alloc_locals; + local x: Uint256; + %{ + import random + random.seed(0) + x = random.randint(2**(ids.n_bits_in_input - 1), 2**ids.n_bits_in_input - 1) + ids.x.low, ids.x.high = split_128(x) + %} + let (res, n_bytes) = uint256_reverse_endian_no_padding(x, pow2_array); + %{ + # Test. + test_function(test_input=ids.x.low + 2**128*ids.x.high, test_output=ids.res.low+2**128*ids.res.high) + %} + return (); +} + +func test_reverse{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}( + n_bits_index: felt, pow2_array: felt* +) { + alloc_locals; + if (n_bits_index == 257) { + return (); + } + test_reverse_inner(n_bits_in_input=n_bits_index, pow2_array=pow2_array); + return test_reverse(n_bits_index=n_bits_index + 1, pow2_array=pow2_array); +} diff --git a/tests/fuzzing/mpt.cairo b/tests/fuzzing/mpt.cairo new file mode 100644 index 0000000..effefa9 --- /dev/null +++ b/tests/fuzzing/mpt.cairo @@ -0,0 +1,110 @@ +%builtins output range_check bitwise keccak + +from starkware.cairo.common.alloc import alloc +from starkware.cairo.common.cairo_builtins import BitwiseBuiltin, KeccakBuiltin +from starkware.cairo.common.uint256 import Uint256, uint256_reverse_endian +from starkware.cairo.common.builtin_keccak.keccak import keccak +from starkware.cairo.common.registers import get_fp_and_pc + +from lib.utils import pow2alloc128 +from lib.mpt import verify_mpt_proof + +func main{ + output_ptr: felt*, range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: KeccakBuiltin* +}() { + alloc_locals; + local batch_len: felt; + + %{ ids.batch_len = len(program_input) %} + + let (pow2_array: felt*) = pow2alloc128(); + + verify_n_mpt_proofs{ + range_check_ptr=range_check_ptr, + bitwise_ptr=bitwise_ptr, + keccak_ptr=keccak_ptr, + pow2_array=pow2_array, + }(batch_len, 0); + + return (); +} + +func verify_n_mpt_proofs{ + range_check_ptr, bitwise_ptr: BitwiseBuiltin*, keccak_ptr: KeccakBuiltin*, pow2_array: felt* +}(batch_len: felt, index: felt) { + alloc_locals; + + if (batch_len == index) { + return (); + } + + let (proof: felt**) = alloc(); + let (proof_bytes_len) = alloc(); + local proof_len: felt; + local key: Uint256; + local key_leading_zeroes: felt; + local root: Uint256; + local expected_hash: Uint256; + local expected_bytes_len: felt; + + %{ + from tools.py.utils import bytes_to_8_bytes_chunks_little, split_128, reverse_endian_256, count_leading_zero_nibbles_from_hex + + def encode_proof(proof): + chunks = [] + bytes_len = [] + + for node in proof: + node_bytes = bytes.fromhex(node) + bytes_len.append(len(node_bytes)) + chunks.append(bytes_to_8_bytes_chunks_little(node_bytes)) + + return (chunks, bytes_len) + + + batch = program_input[ids.index] + (chunks, bytes_len) = encode_proof(batch["proof"]) + + segments.write_arg(ids.proof, chunks) + segments.write_arg(ids.proof_bytes_len, bytes_len) + ids.proof_len = len(chunks) + + + # handle root + reversed_root = reverse_endian_256(int(batch["root"], 16)) + (root_low, root_high) = split_128(reversed_root) + ids.root.low = root_low + ids.root.high = root_high + + #handle key + ids.key_leading_zeroes = count_leading_zero_nibbles_from_hex(batch["key"]) + (key_low, key_high) = split_128(int(batch["key"], 16)) + ids.key.low = key_low + ids.key.high = key_high + + reversed_hash = reverse_endian_256(int(batch["value_hash"], 16)) + (hash_low, hash_high) = split_128(reversed_hash) + ids.expected_hash.low = hash_low + ids.expected_hash.high = hash_high + + ids.expected_bytes_len = batch["value_len"] + %} + + let (result, result_bytes_len) = verify_mpt_proof( + mpt_proof=proof, + mpt_proof_bytes_len=proof_bytes_len, + mpt_proof_len=proof_len, + key_be=key, + key_be_leading_zeroes_nibbles=key_leading_zeroes, + root=root, + pow2_array=pow2_array, + ); + + assert result_bytes_len = expected_bytes_len; + + let (local value_hash) = keccak(result, result_bytes_len); + assert expected_hash.low = value_hash.low; + assert expected_hash.high = value_hash.high; + + return verify_n_mpt_proofs(batch_len, index + 1); +} diff --git a/tests/rust/Cargo.lock b/tests/rust/Cargo.lock new file mode 100644 index 0000000..79cae1f --- /dev/null +++ b/tests/rust/Cargo.lock @@ -0,0 +1,3113 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + +[[package]] +name = "alloy-primitives" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "hex-literal", + "itoa", + "k256", + "keccak-asm", + "proptest", + "rand", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-provider" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-json-rpc", + "alloy-network", + "alloy-primitives", + "alloy-rpc-client", + "alloy-rpc-trace-types", + "alloy-rpc-types", + "alloy-transport", + "alloy-transport-http", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "lru", + "reqwest", + "serde_json", + "tokio", + "tracing", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "alloy-transport-http", + "futures", + "pin-project", + "reqwest", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-trace-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types", + "alloy-serde", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + +[[package]] +name = "alloy-transport" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-json-rpc", + "base64 0.22.0", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "url", + "wasm-bindgen-futures", +] + +[[package]] +name = "alloy-transport-http" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=52d16d3#52d16d33e125670e952b38d888eaefc560738cc2" +dependencies = [ + "alloy-json-rpc", + "alloy-transport", + "reqwest", + "serde_json", + "tower", + "url", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "ark-ff" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" +dependencies = [ + "ark-ff-asm 0.3.0", + "ark-ff-macros 0.3.0", + "ark-serialize 0.3.0", + "ark-std 0.3.0", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm 0.4.2", + "ark-ff-macros 0.4.2", + "ark-serialize 0.4.2", + "ark-std 0.4.0", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.4.0", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std 0.3.0", + "digest 0.9.0", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-std 0.4.0", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "auto_impl" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.5", +] + +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "const-hex" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +dependencies = [ + "cfg-if", + "cpufeatures", + "hex", + "proptest", + "serde", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 2.0.60", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.3", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "eth-trie-proofs" +version = "0.1.0" +source = "git+https://github.com/HerodotusDev/eth-trie-proofs.git?branch=main#3dcc33cec133fd9c6b5501fb66555c13602d57ba" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rlp", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-transport", + "alloy-transport-http", + "clap", + "eth_trie", + "ethereum-types", + "reqwest", + "serde", + "serde_json", + "serde_with", + "tokio", + "url", +] + +[[package]] +name = "eth_trie" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3aeb0284b473041df2419a28e3cdf0c64a78d2b9511af4b6e40bad3964b172" +dependencies = [ + "ethereum-types", + "hashbrown 0.14.3", + "keccak-hash", + "log", + "parking_lot", + "rlp", +] + +[[package]] +name = "ethbloom" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "fastrand" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "fastrlp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", +] + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "keccak-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +dependencies = [ + "digest 0.10.7", + "sha3-asm", +] + +[[package]] +name = "keccak-hash" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b286e6b663fb926e1eeb68528e69cb70ed46c6d65871a21b2215ae8154c6d3c" +dependencies = [ + "primitive-types", + "tiny-keccak", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.3", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parity-scale-codec" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.48.5", +] + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "primitive-types" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags 2.5.0", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "ruint" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" +dependencies = [ + "alloy-rlp", + "ark-ff 0.3.0", + "ark-ff 0.4.2", + "bytes", + "fastrlp", + "num-bigint", + "num-traits", + "parity-scale-codec", + "primitive-types", + "proptest", + "rand", + "rlp", + "ruint-macro", + "serde", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" + +[[package]] +name = "rust" +version = "0.1.0" +dependencies = [ + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-rlp", + "alloy-rpc-client", + "alloy-rpc-types", + "alloy-transport", + "alloy-transport-http", + "eth-trie-proofs", + "eth_trie", + "ethereum-types", + "rand", + "reqwest", + "serde", + "serde_json", + "serde_with", + "tiny-keccak", + "tokio", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.22", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "semver-parser" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] + +[[package]] +name = "serde" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.198" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "serde_json" +version = "1.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3-asm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +dependencies = [ + "cc", + "cfg-if", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.60", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "zeroize" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] diff --git a/tests/rust/Cargo.toml b/tests/rust/Cargo.toml new file mode 100644 index 0000000..e2c5bad --- /dev/null +++ b/tests/rust/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +[dependencies] +eth-trie-proofs = { git = "https://github.com/HerodotusDev/eth-trie-proofs.git", branch = "main" } +alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "52d16d3" } +alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "52d16d3" } +alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "52d16d3" } +alloy-transport = { git = "https://github.com/alloy-rs/alloy", rev = "52d16d3" } +alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy", rev = "52d16d3" } +alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy", rev = "52d16d3" } +tokio = { version = "1", features = ["full"] } +alloy-primitives = "0.6.4" +reqwest = "0.11.27" +alloy-rlp = "0.3.4" +serde = "1.0.197" +serde_with = { version = "3.7.0", features = ["hex"] } +serde_json = "1.0.114" +rand = "0.8.4" +tiny-keccak = "2.0.2" +eth_trie = "0.4.0" +ethereum-types = "0.14.1" + +[dev-dependencies] +tokio = { version = "1", features = ["full", "test-util"] } \ No newline at end of file diff --git a/tests/rust/src/main.rs b/tests/rust/src/main.rs new file mode 100644 index 0000000..b074ab3 --- /dev/null +++ b/tests/rust/src/main.rs @@ -0,0 +1,292 @@ +use alloy_network::Ethereum; + +use alloy_primitives::private::alloy_rlp; +use alloy_primitives::{B256, U256}; +use alloy_provider::{Provider, ProviderBuilder, RootProvider}; +use alloy_rpc_client::RpcClient; +use alloy_rpc_types::{Block, BlockTransactions, Transaction}; +use alloy_transport::{RpcError, TransportErrorKind}; +use alloy_transport_http::Http; +use eth_trie::MemoryDB; +use eth_trie::{EthTrie, Trie, TrieError as EthTrieError}; +use eth_trie_proofs::tx_receipt_trie::TxReceiptsMptHandler; +use eth_trie_proofs::tx_trie::TxsMptHandler; +use eth_trie_proofs::Error as TrieError; +use ethereum_types::H256; +use rand::Rng; +use reqwest::Client; +use serde::Serialize; +use serde_with::serde_as; +use std::fs::File; +use std::io::Write; +use std::sync::Arc; +use tiny_keccak::{Hasher, Keccak}; + +#[derive(Debug)] +enum Error { + Trie(TrieError), + Transport(TransportErrorKind), + Rpc(RpcError), + EthTrie(EthTrieError), +} + +struct Fetcher { + provider: RootProvider>, + tx: TxsMptHandler, + receipt: TxReceiptsMptHandler, +} + +#[derive(Debug, Serialize)] +enum ProofType { + #[serde(rename = "tx_proof")] + TxProof, + #[serde(rename = "receipt_proof")] + ReceiptProof, + #[serde(rename = "account_proof")] + AccountProof, +} + +#[serde_with::serde_as] +#[derive(Debug, Serialize)] +pub struct MptProof { + #[serde_as(as = "serde_with::hex::Hex")] + root: B256, + #[serde_as(as = "Vec")] + proof: Vec>, + #[serde_as(as = "serde_with::hex::Hex")] + key: Vec, + kind: ProofType, +} + +impl Fetcher { + fn new(rpc_url: &str) -> Result { + let http = Http::::new(rpc_url.to_string().parse().unwrap()); + let provider = ProviderBuilder::<_, Ethereum>::new() + .provider(RootProvider::new(RpcClient::new(http, true))); + let tx = TxsMptHandler::new(rpc_url)?; + let receipt = TxReceiptsMptHandler::new(rpc_url)?; + Ok(Fetcher { + provider, + tx, + receipt, + }) + } + + async fn generate_block_tx_proofs( + &mut self, + block_number: u64, + ) -> Result, Error> { + let tx_count = self.get_block_txs_count(block_number).await?; + self.tx.build_tx_tree_from_block(block_number).await?; + let mut proofs = vec![]; + for i in 0..tx_count { + let trie_proof = self.tx.get_proof(i)?; + let root = self.tx.get_root().unwrap(); + + // ensure the proof is valid + self.tx.verify_proof(i, trie_proof.clone())?; + + proofs.push(MptProof { + proof: trie_proof, + key: generate_key_from_index(i), + root, + kind: ProofType::TxProof, + }); + } + + Ok(proofs) + } + + async fn generate_block_receipt_proofs( + &mut self, + block_number: u64, + ) -> Result, Error> { + let tx_count = self.get_block_txs_count(block_number).await?; + self.receipt + .build_tx_receipts_tree_from_block(block_number) + .await?; + let mut proofs = vec![]; + for i in 0..tx_count { + let trie_proof = self.receipt.get_proof(i)?; + let root = self.receipt.get_root()?; + + // ensure the proof is valid + self.receipt.verify_proof(i, trie_proof.clone())?; + + proofs.push(MptProof { + proof: trie_proof, + key: generate_key_from_index(i), + root, + kind: ProofType::ReceiptProof, + }); + } + + Ok(proofs) + } + + async fn get_account_proofs(&mut self, block_number: u64) -> Result, Error> { + let block = self.get_block(block_number).await?; + + // fetch all txs from the block + let txs = self.get_block_txs(block_number).await?; + + // retrieve sender and receiver addresses + let mut addresses = vec![]; + for tx in txs { + addresses.push(tx.from); + if let Some(to) = tx.to { + addresses.push(to); + } + } + + let mut proofs = vec![]; + let memdb = Arc::new(MemoryDB::new(true)); + let trie = EthTrie::new(memdb.clone()); + + for address in addresses { + let proof: Vec<_> = self + .provider + .get_proof(address, vec![], Some(block_number.into())) + .await? + .account_proof + .iter() + .map(|x| x.as_ref().to_vec()) + .collect(); + + // ensure the proof is valid + trie.verify_proof( + H256::from_slice(block.header.state_root.as_slice()), + generate_key_from_address(address.0.as_slice()).as_slice(), + proof.clone(), + )?; + + proofs.push(MptProof { + proof, + key: generate_key_from_address(address.0.as_slice()), + root: block.header.state_root, + kind: ProofType::AccountProof, + }); + } + + Ok(proofs) + } + + async fn get_block(&self, block_number: u64) -> Result { + match self.provider.get_block(block_number.into(), false).await { + Ok(Some(block)) => Ok(block), + _ => panic!(), + } + } + + async fn get_block_txs(&self, block_number: u64) -> Result, Error> { + let block = self.provider.get_block(block_number.into(), true).await?; + match block.unwrap().transactions { + BlockTransactions::Full(txs) => Ok(txs), + _ => panic!(), + } + } + + async fn get_block_txs_count(&self, block_number: u64) -> Result { + let block = self.provider.get_block(block_number.into(), false).await?; + match block.unwrap().transactions { + BlockTransactions::Hashes(hashes) => Ok(hashes.len() as u64), + _ => panic!(), + } + } + + async fn generate_random_block_proofs( + &mut self, + num_blocks: u32, + ) -> Result, Error> { + let mut rng = rand::thread_rng(); + let mut proofs = vec![]; + + // Fetch the current block number + let current_block_number: u64 = self.provider.get_block_number().await?; + for _ in 0..num_blocks { + // As there is a bug in the underlying alloy library, we need to start with the byzantium hardfork. https://github.com/alloy-rs/alloy/issues/630 + let block_number = rng.gen_range(4370000..current_block_number); + println!("Selected block: {:?}", block_number); + match self.generate_block_tx_proofs(block_number).await { + Ok(proof) => proofs.extend(proof), + Err(Error::Trie(TrieError::TxNotFound)) => continue, // found block no txs + Err(e) => return Err(e), + } + + match self.generate_block_receipt_proofs(block_number).await { + Ok(proof) => proofs.extend(proof), + Err(Error::Trie(TrieError::TxNotFound)) => continue, // found block no txs + Err(e) => return Err(e), + } + + let account_proofs = self.get_account_proofs(block_number).await?; + proofs.extend(account_proofs); + } + + Ok(proofs) + } +} + +#[tokio::main] +async fn main() -> Result<(), Error> { + // Create a new Fetcher instance + let mut fetcher = + Fetcher::new("")?; + + // Generate random block proofs + let proofs = fetcher.generate_random_block_proofs(5).await?; + // let proofs = fetcher.get_account_proofs(19733390).await?; + + export_batch(proofs).unwrap(); + + Ok(()) +} + +fn export_batch(proofs: Vec) -> Result<(), Error> { + let chunks = proofs.chunks(50); + + for (i, chunk) in chunks.enumerate() { + let serialized = serde_json::to_string_pretty(chunk).unwrap(); + + // Write the JSON string to a file + let mut file = File::create(format!("mpt_proofs_{}.json", i)).unwrap(); + file.write_all(serialized.as_bytes()).unwrap(); + } + + Ok(()) +} +fn generate_key_from_address(address: &[u8]) -> Vec { + let mut hasher = Keccak::v256(); + hasher.update(address); + let mut output = [0u8; 32]; + hasher.finalize(&mut output); + output.to_vec() +} + +fn generate_key_from_index(index: u64) -> Vec { + alloy_rlp::encode(U256::from(index)) +} + +impl From for Error { + fn from(error: TrieError) -> Self { + Error::Trie(error) + } +} + +impl From for Error { + fn from(error: EthTrieError) -> Self { + Error::EthTrie(error) + } +} + +impl From for Error { + fn from(error: TransportErrorKind) -> Self { + Error::Transport(error) + } +} + +impl From> for Error { + fn from(error: RpcError) -> Self { + Error::Rpc(error) + } +} diff --git a/tools/make/build.sh b/tools/make/build.sh index c4085e4..06d9370 100755 --- a/tools/make/build.sh +++ b/tools/make/build.sh @@ -20,7 +20,7 @@ process_cairo_file() { export -f process_cairo_file # Use --halt now,fail=1 to return non-zero if any task fails -find ./lib ./tests/cairo_programs -name "*.cairo" | parallel --halt now,fail=1 process_cairo_file +find ./lib ./tests/fuzzing ./tests/cairo_programs -name "*.cairo" | parallel --halt now,fail=1 process_cairo_file # Capture the exit status of parallel exit_status=$? diff --git a/tools/make/cairo_tests.sh b/tools/make/cairo_tests.sh index eab0b97..90cb3d8 100755 --- a/tools/make/cairo_tests.sh +++ b/tools/make/cairo_tests.sh @@ -27,7 +27,7 @@ source venv/bin/activate # Export the function so it's available in subshells export -f run_tests -# Find all .cairo files under src/ and tests/ directories and format them in parallel +# Find all .cairo files under tests/cairo_programs and run them in parallel # Using --halt soon,fail=1 to stop at the first failure find ./tests/cairo_programs -name '*.cairo' | parallel --halt soon,fail=1 run_tests diff --git a/tools/make/ci_local.sh b/tools/make/ci_local.sh index 54e11a2..4e219cc 100755 --- a/tools/make/ci_local.sh +++ b/tools/make/ci_local.sh @@ -18,6 +18,9 @@ echo "Run Python Format Check..." echo "Run Cairo Tests..." (source ./tools/make/cairo_tests.sh) +echo "Run MPT Tests..." +(source ./tools/make/fuzzer.sh tests/fuzzing/mpt.cairo --ci) + # End time end_time=$SECONDS diff --git a/tools/make/fuzzer.sh b/tools/make/fuzzer.sh new file mode 100755 index 0000000..da35390 --- /dev/null +++ b/tools/make/fuzzer.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +# Activate virtual environment +source venv/bin/activate + +# Define a boolean argument +IS_CI_RUN=false + +for arg in "$@" +do + if [ "$arg" == "--ci" ] + then + IS_CI_RUN=true + fi +done + +# Get the Cairo file from the command line argument +cairo_file="$1" +filename=$(basename "$cairo_file" .cairo) + +echo "Running fuzzer for $filename" + +# Define the log file path incorporating the filename +LOG_FILE="test_results_${filename}.log" + +# Ensure the log file exists, otherwise create it +touch "$LOG_FILE" + +# Export the log file path to be available in subshells +export LOG_FILE +export filenname + +process_input() { + local input_file="$2" + local filename="$1" + local batchname=$(basename "$input_file" .json) + local temp_output=$(mktemp) + + + # Attempt to run the compiled program and capture output + local start_time=$(date +%s) + cairo-run --program="build/compiled_cairo_files/$filename.json" --program_input=$input_file --layout=starknet_with_keccak >> "$temp_output" 2>&1 + local status=$? + local end_time=$(date +%s) + local duration=$((end_time - start_time)) + + # Handle output based on success or failure + if [ $status -eq 0 ]; then + echo "$(date '+%Y-%m-%d %H:%M:%S') - Successful $input_file: Duration ${duration} seconds" + else + echo "$(date '+%Y-%m-%d %H:%M:%S') - Failed: $input_file" + cat "$temp_output" # Output the error to the console + fi + + cat "$temp_output" >> "$LOG_FILE" + rm -f "$temp_output" # Clean up temporary file + return $status +} + +export -f process_input + +# Ensure the Cairo file is compiled before running parallel tests +cairo-compile --cairo_path="packages/eth_essentials" "$cairo_file" --output "build/compiled_cairo_files/$filename.json" +# cairo-run --program="build/compiled_cairo_files/$filename.json" --program_input=tests/fuzzing/fixtures/mpt_proofs_5.json --layout=starknet_with_keccak +# Use --halt now,fail=1 to return non-zero if any task fails +find ./tests/fuzzing/fixtures -name "*.json" | parallel --halt now,fail=1 process_input $filename + +# Clone the repository if the directory doesn't exist +if [ ! -d "mpt-fixtures" ]; then + git clone https://github.com/HerodotusDev/mpt-fixtures +fi + +echo "Starting tests..." +if $IS_CI_RUN; then + # Run the tests in parallel + find ./mpt-fixtures/fixtures/resolved -name "*.json" | parallel --halt soon,fail=1 process_input $filename +else + # Run the tests in parallel + find ./mpt-fixtures/fixtures/autogen -name "*.json" | parallel process_input $filename +fi + +# Capture the exit status of parallel +exit_status=$? + +# Exit with the captured status +echo "Parallel execution exited with status: $exit_status" +exit $exit_status diff --git a/tools/py/utils.py b/tools/py/utils.py index ae23cbc..abc16d9 100644 --- a/tools/py/utils.py +++ b/tools/py/utils.py @@ -9,6 +9,9 @@ def split_128(a): """Takes in value, returns uint256-ish tuple.""" + assert ( + 0 <= a.bit_length() <= 256 + ), f"split_128 input exceeds maximum bit length of 256, got {a.bit_length()}" return (a & ((1 << 128) - 1), a >> 128) @@ -21,6 +24,77 @@ def reverse_endian_256(x: int): return int.from_bytes(x.to_bytes(32, "big"), "little") +def parse_int_to_bytes(x: int) -> bytes: + """ + Convert an integer to a bytes object. + If the number of bytes is odd, left pad with one leading zero. + """ + hex_str = hex(x)[2:] + if len(hex_str) % 2 == 1: + hex_str = "0" + hex_str + return bytes.fromhex(hex_str) + + +def count_trailing_zero_bytes_from_int(number: int) -> int: + """ + Counts the number of trailing zero bytes in the hexadecimal representation of an integer. + + Args: + number (int): The integer to analyze. + + Returns: + int: The number of trailing zero bytes. + """ + # Convert the integer to a hexadecimal string without the '0x' prefix + hex_str = format(number, "x") + + # Ensure the hex string length is even for complete byte representation + if len(hex_str) % 2 != 0: + hex_str = "0" + hex_str + + # Initialize count of trailing zero bytes + trailing_zero_bytes = 0 + + # Reverse the string to start checking from the last character + reversed_hex_str = hex_str[::-1] + + # Iterate over each pair of characters in the reversed string + for i in range(0, len(reversed_hex_str), 2): + if reversed_hex_str[i : i + 2] == "00": + trailing_zero_bytes += 1 + else: + break # Stop counting at the first non-zero byte + + return trailing_zero_bytes + + +def count_leading_zero_nibbles_from_hex(hex_str: str) -> int: + """ + Counts the number of leading zero nibbles in a hexadecimal string. + + Args: + hex_str (str): The hexadecimal string to analyze. + + Returns: + int: The number of leading zero nibbles. + """ + # Remove any leading '0x' if present + if hex_str.startswith("0x"): + hex_str = hex_str[2:] + + # Initialize count of leading zero nibbles + leading_zero_nibbles = 0 + + # Iterate over each character in the string + for char in hex_str: + if char == "0": + leading_zero_nibbles += 1 + else: + break # Stop counting at the first non-zero nibble + + return leading_zero_nibbles + + def rpc_request(url, rpc_request): headers = {"Content-Type": "application/json"} response = requests.post(url=url, headers=headers, data=json.dumps(rpc_request))