From 2cd5cffbb2fdf0fb7852cf258cdf2b3796191fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kami=C5=84ski?= Date: Tue, 17 Oct 2023 11:32:19 +0200 Subject: [PATCH] feat: Starknet storage proof verifier (#189) Starknet storage proof verifier. ## Pull Request type Please check the type of change your PR introduces: - [ ] Bugfix - [x] Feature - [ ] Code style update (formatting, renaming) - [ ] Refactoring (no functional changes, no API changes) - [ ] Build-related changes - [ ] Documentation content changes - [ ] Other (please describe): ## What is the current behavior? Issue Number: N/A ## What is the new behavior? - - - ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information --- Scarb.toml | 1 + src/data_structures/README.md | 22 +- src/data_structures/src/lib.cairo | 1 - src/data_structures/src/tests.cairo | 1 - src/merkle_tree/README.md | 12 + src/merkle_tree/Scarb.toml | 8 + src/merkle_tree/src/lib.cairo | 6 + .../src/merkle_tree.cairo | 4 - src/merkle_tree/src/storage_proof.cairo | 163 +++++ src/merkle_tree/src/tests.cairo | 3 + .../src/tests/get_storage_proof.sh | 18 + .../src/tests/merkle_tree_test.cairo | 4 +- .../src/tests/storage_proof_filter.jq | 34 ++ .../src/tests/storage_proof_test.cairo | 58 ++ .../src/tests/storage_proof_test_data.cairo | 574 ++++++++++++++++++ src/storage/src/lib.cairo | 1 - 16 files changed, 886 insertions(+), 24 deletions(-) create mode 100644 src/merkle_tree/README.md create mode 100644 src/merkle_tree/Scarb.toml create mode 100644 src/merkle_tree/src/lib.cairo rename src/{data_structures => merkle_tree}/src/merkle_tree.cairo (98%) create mode 100644 src/merkle_tree/src/storage_proof.cairo create mode 100644 src/merkle_tree/src/tests.cairo create mode 100755 src/merkle_tree/src/tests/get_storage_proof.sh rename src/{data_structures => merkle_tree}/src/tests/merkle_tree_test.cairo (98%) create mode 100644 src/merkle_tree/src/tests/storage_proof_filter.jq create mode 100644 src/merkle_tree/src/tests/storage_proof_test.cairo create mode 100644 src/merkle_tree/src/tests/storage_proof_test_data.cairo diff --git a/Scarb.toml b/Scarb.toml index 73994bc6..732099f5 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -4,6 +4,7 @@ members = [ "src/encoding", "src/linalg", "src/math", + "src/merkle_tree", "src/numeric", "src/searching", "src/sorting", diff --git a/src/data_structures/README.md b/src/data_structures/README.md index 33cde852..56907906 100644 --- a/src/data_structures/README.md +++ b/src/data_structures/README.md @@ -1,25 +1,17 @@ # Data structures ## [Array extension](./src/array_ext.cairo) -A collection of handy functions to help with array manipulation. - -## [Merkle Tree](./src/merkle_tree.cairo) - -The Merkle tree algorithm is a cryptographic hashing algorithm used to create a hash tree, which is a tree data structure where each leaf node represents a data block and each non-leaf node represents a hash of its child nodes. -The purpose of the Merkle tree algorithm is to provide a way to verify the integrity and authenticity of large amounts of data without needing to store the entire data set. The algorithm has applications in various areas of computer science, including cryptocurrency, file sharing, and database management. -The Merkle tree algorithm is also used in creating digital signatures and verifying the authenticity of transactions. -By providing a secure and efficient way to verify data integrity, the Merkle tree algorithm is an important tool in cryptography and information security. -A generic implementation is available to manage both pedersen (legacy) and poseidon hash methods. +A collection of handy functions to help with array manipulation. ## [Queue](./src/queue.cairo) -The queue is used to store and manipulate a collection of elements where the elements are processed in a first-in, first-out (FIFO) order. -The purpose of the queue algorithm is to provide a way to manage and process elements in a specific order, where the oldest element is processed first. -The queue algorithm has applications in various areas of computer science, including operating systems, networking, and data processing. It is used to manage tasks that are processed in a specific order and ensure that the order is maintained. +The queue is used to store and manipulate a collection of elements where the elements are processed in a first-in, first-out (FIFO) order. +The purpose of the queue algorithm is to provide a way to manage and process elements in a specific order, where the oldest element is processed first. +The queue algorithm has applications in various areas of computer science, including operating systems, networking, and data processing. It is used to manage tasks that are processed in a specific order and ensure that the order is maintained. By providing a simple and efficient way to manage elements in a specific order, the queue algorithm is an important tool in computer science and software development. ## [Stack](./src/stack.cairo) -The stack is used to store and manipulate a collection of elements where the elements are processed in a last-in, first-out (LIFO) order. -The purpose of the stack algorithm is to provide a way to manage and process elements in a specific order, where the most recently added element is processed first. -The stack algorithm has applications in various areas of computer science, including programming languages, operating systems, and network protocols. It is used to manage tasks that require a temporary storage of data or information, and also for processing recursive function calls. +The stack is used to store and manipulate a collection of elements where the elements are processed in a last-in, first-out (LIFO) order. +The purpose of the stack algorithm is to provide a way to manage and process elements in a specific order, where the most recently added element is processed first. +The stack algorithm has applications in various areas of computer science, including programming languages, operating systems, and network protocols. It is used to manage tasks that require a temporary storage of data or information, and also for processing recursive function calls. By providing a simple and efficient way to manage elements in a specific order, the stack algorithm is an important tool in computer science and software development. \ No newline at end of file diff --git a/src/data_structures/src/lib.cairo b/src/data_structures/src/lib.cairo index afdaab53..f4bb99fb 100644 --- a/src/data_structures/src/lib.cairo +++ b/src/data_structures/src/lib.cairo @@ -1,7 +1,6 @@ mod array_ext; mod byte_array_ext; mod byte_array_reader; -mod merkle_tree; mod queue; mod stack; mod vec; diff --git a/src/data_structures/src/tests.cairo b/src/data_structures/src/tests.cairo index 8375bb05..555a33cb 100644 --- a/src/data_structures/src/tests.cairo +++ b/src/data_structures/src/tests.cairo @@ -1,7 +1,6 @@ mod array_ext_test; mod byte_array_ext_test; mod byte_array_reader_test; -mod merkle_tree_test; mod queue_test; mod stack_test; mod vec_test; diff --git a/src/merkle_tree/README.md b/src/merkle_tree/README.md new file mode 100644 index 00000000..d04cdeba --- /dev/null +++ b/src/merkle_tree/README.md @@ -0,0 +1,12 @@ +# Merkle Tree related stuff + +## [Merkle Tree](./src/merkle_tree.cairo) + +The Merkle tree algorithm is a cryptographic hashing algorithm used to create a hash tree, which is a tree data structure where each leaf node represents a data block and each non-leaf node represents a hash of its child nodes. +The purpose of the Merkle tree algorithm is to provide a way to verify the integrity and authenticity of large amounts of data without needing to store the entire data set. The algorithm has applications in various areas of computer science, including cryptocurrency, file sharing, and database management. +The Merkle tree algorithm is also used in creating digital signatures and verifying the authenticity of transactions. +By providing a secure and efficient way to verify data integrity, the Merkle tree algorithm is an important tool in cryptography and information security. +A generic implementation is available to manage both pedersen (legacy) and poseidon hash methods. + +## [Starknet Storage Proof Verifier](./src/storage_proof.cairo) +Implementation of Starknet ([storage proofs](https://docs.starknet.io/documentation/architecture_and_concepts/State/starknet-state/)) returned by `pathfinder_getproof` API endpoint ([see](https://github.com/eqlabs/pathfinder/blob/main/doc/rpc/pathfinder_rpc_api.json)). \ No newline at end of file diff --git a/src/merkle_tree/Scarb.toml b/src/merkle_tree/Scarb.toml new file mode 100644 index 00000000..566a04ca --- /dev/null +++ b/src/merkle_tree/Scarb.toml @@ -0,0 +1,8 @@ +[package] +name = "alexandria_merkle_tree" +version = "0.1.0" +description = "Merkle tree related stuff" +homepage = "https://github.com/keep-starknet-strange/alexandria/tree/src/merkle_tree" + +[dependencies] +starknet.workspace = true diff --git a/src/merkle_tree/src/lib.cairo b/src/merkle_tree/src/lib.cairo new file mode 100644 index 00000000..44b79b55 --- /dev/null +++ b/src/merkle_tree/src/lib.cairo @@ -0,0 +1,6 @@ +mod merkle_tree; +mod storage_proof; + + +#[cfg(test)] +mod tests; diff --git a/src/data_structures/src/merkle_tree.cairo b/src/merkle_tree/src/merkle_tree.cairo similarity index 98% rename from src/data_structures/src/merkle_tree.cairo rename to src/merkle_tree/src/merkle_tree.cairo index 3edc4abd..e9f5f425 100644 --- a/src/data_structures/src/merkle_tree.cairo +++ b/src/merkle_tree/src/merkle_tree.cairo @@ -24,10 +24,6 @@ //! let root = merkle_tree.compute_root(leaf, proof); //! ``` -// Core lib imports -use array::{ArrayTrait, SpanTrait}; -use traits::{Into, Copy, Drop}; - /// Hasher trait. trait HasherTrait { diff --git a/src/merkle_tree/src/storage_proof.cairo b/src/merkle_tree/src/storage_proof.cairo new file mode 100644 index 00000000..dd935146 --- /dev/null +++ b/src/merkle_tree/src/storage_proof.cairo @@ -0,0 +1,163 @@ +use pedersen::PedersenTrait; +use poseidon::PoseidonTrait; +use hash::HashStateTrait; + +#[derive(Drop)] +struct BinaryNode { + left: felt252, + right: felt252, +} + +#[derive(Drop, Copy)] +struct EdgeNode { + child: felt252, + path: felt252, + length: u8, +} + +#[derive(Drop)] +enum TrieNode { + Binary: BinaryNode, + Edge: EdgeNode, +} + +#[derive(Destruct)] +struct ContractData { + class_hash: felt252, + nonce: felt252, + contract_state_hash_version: felt252, + storage_proof: Array +} + +#[derive(Destruct)] +struct ContractStateProof { + class_commitment: felt252, + contract_proof: Array, + contract_data: ContractData +} + +/// Verify Starknet storage proof. For reference see: +/// - ([state](https://docs.starknet.io/documentation/architecture_and_concepts/State/starknet-state/)) +/// - ([pathfinder_getproof API endpoint](https://github.com/eqlabs/pathfinder/blob/main/doc/rpc/pathfinder_rpc_api.json)) +/// - ([pathfinder storage implementation](https://github.com/eqlabs/pathfinder/blob/main/crates/merkle-tree/src/tree.rs)) +/// # Arguments +/// * `expected_state_commitment` - state root `proof` is going to be verified against +/// * `contract_address` - `contract_address` of the value to be verified +/// * `storage_address` - `storage_address` of the value to be verified +/// * `proof` - `ContractStateProof` representing storage proof +/// # Returns +/// * `felt252` - `value` at `storage_address` if verified, panic otherwise. +fn verify( + expected_state_commitment: felt252, + contract_address: felt252, + storage_address: felt252, + proof: ContractStateProof +) -> felt252 { + let contract_data = proof.contract_data; + + let (contract_root_hash, storage_value) = traverse( + storage_address, contract_data.storage_proof + ); + + let contract_state_hash = pedersen_hash_4( + contract_data.class_hash, + contract_root_hash, + contract_data.nonce, + contract_data.contract_state_hash_version + ); + + let (contracts_tree_root, expected_contract_state_hash) = traverse( + contract_address, proof.contract_proof + ); + + assert(expected_contract_state_hash == contract_state_hash, 'wrong contract_state_hash'); + + let state_commitment = poseidon_hash( + 'STARKNET_STATE_V0', contracts_tree_root, proof.class_commitment + ); + + assert(expected_state_commitment == state_commitment, 'wrong state_commitment'); + + storage_value +} + +fn traverse(expected_path: felt252, proof: Array) -> (felt252, felt252) { + let mut path: felt252 = 0; + let mut remaining_depth: u8 = 251; + + let mut nodes = proof.span(); + let expected_path_u256: u256 = expected_path.into(); + + let leaf = *match nodes.pop_back().unwrap() { + TrieNode::Binary(_) => panic_with_felt252('invalid leaf type'), + TrieNode::Edge(edge) => edge + }; + + let mut expected_hash = node_hash(@TrieNode::Edge(leaf)); + let value = leaf.child; + let mut path = leaf.path; + let mut path_length_pow2 = pow(2, leaf.length); + + loop { + match nodes.pop_back() { + Option::Some(node) => { + match node { + TrieNode::Binary(binary_node) => { + if expected_path_u256 & path_length_pow2.into() > 0 { + assert(expected_hash == *binary_node.right, 'invalid node hash'); + path += path_length_pow2; + } else { + assert(expected_hash == *binary_node.left, 'invalid node hash'); + }; + path_length_pow2 *= 2; + }, + TrieNode::Edge(edge_node) => { + assert(expected_hash == *edge_node.child, 'invalid node hash'); + path += *edge_node.path * path_length_pow2; + path_length_pow2 *= pow(2, *edge_node.length); + } + } + expected_hash = node_hash(node); + }, + Option::None => { break; } + }; + }; + assert(expected_path == path, 'invalid proof path'); + (expected_hash, value) +} + +#[inline] +fn node_hash(node: @TrieNode) -> felt252 { + match node { + TrieNode::Binary(binary) => pedersen_hash(*binary.left, *binary.right), + TrieNode::Edge(edge) => pedersen_hash(*edge.child, *edge.path) + (*edge.length).into() + } +} + +// TODO: replace with lookup table once array constants are available in Cairo +fn pow(x: felt252, n: u8) -> felt252 { + if n == 0 { + 1 + } else if n == 1 { + x + } else if (n & 1) == 1 { + x * pow(x * x, n / 2) + } else { + pow(x * x, n / 2) + } +} + +#[inline(always)] +fn pedersen_hash(a: felt252, b: felt252) -> felt252 { + PedersenTrait::new(a).update(b).finalize() +} + +#[inline(always)] +fn pedersen_hash_4(a: felt252, b: felt252, c: felt252, d: felt252) -> felt252 { + PedersenTrait::new(a).update(b).update(c).update(d).finalize() +} + +#[inline(always)] +fn poseidon_hash(a: felt252, b: felt252, c: felt252) -> felt252 { + PoseidonTrait::new().update(a).update(b).update(c).finalize() +} diff --git a/src/merkle_tree/src/tests.cairo b/src/merkle_tree/src/tests.cairo new file mode 100644 index 00000000..2a1b7424 --- /dev/null +++ b/src/merkle_tree/src/tests.cairo @@ -0,0 +1,3 @@ +mod merkle_tree_test; +mod storage_proof_test; +mod storage_proof_test_data; diff --git a/src/merkle_tree/src/tests/get_storage_proof.sh b/src/merkle_tree/src/tests/get_storage_proof.sh new file mode 100755 index 00000000..c84e637a --- /dev/null +++ b/src/merkle_tree/src/tests/get_storage_proof.sh @@ -0,0 +1,18 @@ +#! /usr/bin/env bash +set -e; +set -o pipefail; + +curl -s -X POST \ + -H 'Content-Type: application/json' \ + -d '{ + "jsonrpc": "2.0", + "method": "pathfinder_getProof", + "params": { + "block_id": { "block_hash": "'${1}'"}, + "contract_address": "'${2}'", + "keys": ["'${3}'"] + }, + "id": 0 + }' \ + $STARKNET_RPC \ + | jq -r -f storage_proof_filter.jq \ No newline at end of file diff --git a/src/data_structures/src/tests/merkle_tree_test.cairo b/src/merkle_tree/src/tests/merkle_tree_test.cairo similarity index 98% rename from src/data_structures/src/tests/merkle_tree_test.cairo rename to src/merkle_tree/src/tests/merkle_tree_test.cairo index b899ff96..6b873ee7 100644 --- a/src/data_structures/src/tests/merkle_tree_test.cairo +++ b/src/merkle_tree/src/tests/merkle_tree_test.cairo @@ -1,5 +1,5 @@ // Internal imports -use alexandria_data_structures::merkle_tree::{ +use alexandria_merkle_tree::merkle_tree::{ Hasher, MerkleTree, pedersen::PedersenHasherImpl, poseidon::PoseidonHasherImpl, MerkleTreeTrait, MerkleTreeImpl }; @@ -7,7 +7,7 @@ use alexandria_data_structures::merkle_tree::{ mod regular_call_merkle_tree_pedersen { // Internal imports - use alexandria_data_structures::merkle_tree::{ + use alexandria_merkle_tree::merkle_tree::{ Hasher, MerkleTree, pedersen::PedersenHasherImpl, MerkleTreeTrait, }; #[test] diff --git a/src/merkle_tree/src/tests/storage_proof_filter.jq b/src/merkle_tree/src/tests/storage_proof_filter.jq new file mode 100644 index 00000000..79fb7988 --- /dev/null +++ b/src/merkle_tree/src/tests/storage_proof_filter.jq @@ -0,0 +1,34 @@ +def node: + if has("binary") + then + "TrieNode::Binary( + BinaryNode { + left: \(.binary.left), + right: \(.binary.right), + } + )" + else + "TrieNode::Edge( + EdgeNode { + path: \(.edge.path.value), + length: \(.edge.path.len), + child: \(.edge.child), + } + )" + end +; + +def proof: + "array![\n\(.|map(node) | join(",\n"))\n]" +; + +.result|"ContractStateProof { + class_commitment: \(.class_commitment), + contract_proof: \(.contract_proof | proof), + contract_data: \(.contract_data|"ContractData { + class_hash: \(.class_hash), + nonce: \(.nonce), + contract_state_hash_version: 0, + storage_proof: \(.storage_proofs | .[0] | proof), + }") +}" \ No newline at end of file diff --git a/src/merkle_tree/src/tests/storage_proof_test.cairo b/src/merkle_tree/src/tests/storage_proof_test.cairo new file mode 100644 index 00000000..6a24f32f --- /dev/null +++ b/src/merkle_tree/src/tests/storage_proof_test.cairo @@ -0,0 +1,58 @@ +use alexandria_merkle_tree::storage_proof::{ + ContractStateProof, ContractData, TrieNode, BinaryNode, EdgeNode, verify +}; + +use alexandria_merkle_tree::tests::storage_proof_test_data::{balance_proof, total_balance_proof}; + +const DAI: felt252 = 0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3; +const ETH: felt252 = 0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7; + +#[test] +#[available_gas(2000000)] +fn balance_lsb_proof_test() { + let state_commitment = 0x07dc88984a2d8f9c2a6d2d431b2d8f2c32957da514c16ceef0761b6933121708; + let contract_address = DAI; + let storage_address = 0x4ae51d08cd202d1472587dfe63dbf2d5ec767cbf4218b59b7ab71956780c6ee; + let expected_value = 8700000000000000005; + let proof = balance_proof(); + let value = verify(state_commitment, contract_address, storage_address, proof); + assert(expected_value == value, 'wrong value'); +} + +#[test] +#[should_panic(expected: ('invalid proof path',))] +#[available_gas(2000000)] +fn balance_msb_proof_test() { + let state_commitment = 0x07dc88984a2d8f9c2a6d2d431b2d8f2c32957da514c16ceef0761b6933121708; + let contract_address = DAI; + let storage_address = 0x4ae51d08cd202d1472587dfe63dbf2d5ec767cbf4218b59b7ab71956780c6ef; + let expected_value = 8700000000000000005; + let proof = balance_proof(); + let value = verify(state_commitment, contract_address, storage_address, proof); + assert(expected_value == value, 'wrong value'); +} + +#[test] +#[should_panic(expected: ('invalid node hash',))] +#[available_gas(2000000)] +fn wrong_contract_address_proof_test() { + let state_commitment = 0x07dc88984a2d8f9c2a6d2d431b2d8f2c32957da514c16ceef0761b6933121708; + let contract_address = ETH; + let storage_address = 0x4ae51d08cd202d1472587dfe63dbf2d5ec767cbf4218b59b7ab71956780c6ee; + let expected_value = 8700000000000000005; + let proof = balance_proof(); + let value = verify(state_commitment, contract_address, storage_address, proof); + assert(expected_value == value, 'wrong value'); +} + +#[test] +#[available_gas(50000000)] +fn total_balance_lsb_proof_test() { + let state_commitment = 0x07dc88984a2d8f9c2a6d2d431b2d8f2c32957da514c16ceef0761b6933121708; + let contract_address = DAI; + let storage_address = 0x37a9774624a0e3e0d8e6b72bd35514f62b3e8e70fbaff4ed27181de4ffd4604; + let expected_value = 2970506847688829412026631; + let proof = total_balance_proof(); + let value = verify(state_commitment, contract_address, storage_address, proof); + assert(expected_value == value, 'wrong value'); +} diff --git a/src/merkle_tree/src/tests/storage_proof_test_data.cairo b/src/merkle_tree/src/tests/storage_proof_test_data.cairo new file mode 100644 index 00000000..75d6a242 --- /dev/null +++ b/src/merkle_tree/src/tests/storage_proof_test_data.cairo @@ -0,0 +1,574 @@ +use alexandria_merkle_tree::storage_proof::{ + ContractStateProof, ContractData, TrieNode, BinaryNode, EdgeNode +}; + +fn balance_proof() -> ContractStateProof { + // func _balances(user : felt) -> (res : Uint256): + // get_storage_var_address('_balances', 0x063c94d6B73eA2284338f464f86F33E12642149F763Cd8E76E035E8E6A5Bb0e6) + // storage_address = 0x4ae51d08cd202d1472587dfe63dbf2d5ec767cbf4218b59b7ab71956780c6ee + // ./get_storage_proof.sh 0x02f63993df97fb44439d8e2e999c8b9b51efba1eff78e5c994c709c82b442e65 \ + // 0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3 \ + // 0x4ae51d08cd202d1472587dfe63dbf2d5ec767cbf4218b59b7ab71956780c6ee + + ContractStateProof { + class_commitment: 0x5eed4c30c17df1a41905c9824f2a296b6f77e91f0f017290752a60fbb8f9ff7, + contract_proof: array![ + TrieNode::Binary( + BinaryNode { + left: 0x74b59299e8315ce3c9d679b0a439f8bd6d55f1f7544b98852c85c953ec57e8, + right: 0x2390819e385bb1876e077b5ed4a4bae52c0e16ae7efee4c889c3d5247f6fb60, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5ef3be75d230f16f9f62058cd51f33fe511f132400e24ede72fe931d9afcd59, + right: 0x404d825da685c12746a2b2b7089c13561135ac529a6624b848951993331de4f, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5cbf312528ca49ab9012f368994adcb85f778360c68d61ddfa94e5db04e39bf, + right: 0x4df940db2395b5a8929cf658e36b45e88431aa9b0a1513e5318d81e83af66ca, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5e002697a7591f4cb36f024142c249493ea69f2820aae9842b085d9cd20a825, + right: 0x78e4c02f55114f6b4989788d52e2d03bd3416f720d090215a7f95d1178166c6, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4ad60a445f0a47f285861868f332f310b405acc3366a44483b534daefc4061b, + right: 0x4a3bff604eb492f216f053a8756d7c3cb2f80649c4a3fea7d5ed939b24c784c, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x316045f83427fc1a617bb370fa2b1a7a03d462b264729424f52c6ae00e1f71a, + right: 0x7ca38911fbfba4481ea60591a97b01861825c1f908dd7fc3141192b79b55d43, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x17bf798cac821552f0e3d804dd9876e286c63d64d64aca19aea00ea9110ff58, + right: 0x33b2593a0e40d4ed0ddb6d8b7b824a2bde13062dc405c2394a8a797c35b4b32, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x1a78b3285e1f816ec7fdeeecbd7de855c3fe50e49cb9d294c0fbe698a8f0964, + right: 0x737aebdf31cbf55171144bd658e0e82862541b0af78d3241e13de77015f1ce3, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x7267f91ecdc6e579864613a406750bc80363a2be5ff863f020e5531eb8d947a, + right: 0x65bcc933abbb3c71cf3edd535204f34eb58a7329a53688039733420571f45fc, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0xac490c5cda65c26fe042c08d9bec48f399db1b0c551eb3fcbcf5fc51643beb, + right: 0x574edd4ea6655ada56844d7b7797af4fb66fa8e86361ee201d817de885ab751, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x54407ae16b65fd67d64fc8528f7240cd4c6914041dd9e3bf7c56cbab58eb42e, + right: 0x5e7d51e63c8c33f864418dd61e720cfcda9363d9b6b1c5de11f68b2d0a9a448, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4550dba3e8b473bc2b4cc6c99c43ec90864930f4ec06affb267f24ad16df0b5, + right: 0x545515cd797a277cdb88ab7efaa63ea979220696e51c6173de23984ff1746c4, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x14fa907e7e9633b6f3dcabfe07e8dac02e0aea480949bfd0f8dea13ecb5c50c, + right: 0x5448b1aac9acedab60b5401d6330bfabd397f1086ab42948ed1fa81e38a2157, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x1139a46c5e89fbcc483b8726d3e7707122b57ccdf955df4216cb1a93ffffd7a, + right: 0x6729ff6fec2dfcc6535bc4eea26fc4eb65e0285d4f8ae0fe6be4c343d9bb720, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x3d7dcabc79ce522ffb88b167edfd51896a6430a456250290f2ac1cdbe6572b3, + right: 0x990164dd962c5d48dd9a98cd8845bfdd483cbc07bbbfcd2c19daee84992e28, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x59cc416528b7228ed0064a393ed60462f5e556d5a236f7b94ea8d510641cd64, + right: 0x325c342f00e73f97c8a1ff2462c754dbb27b967223954f690e1d069e5088599, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x3c976052cb6c461679e159c1b711e8d0261d240745931ea399edf389848f99d, + right: 0x4f65e0c2b833c972c02ad133e6aa152a6e9d15bca277c2b163bc09c8b2e2b1c, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x338b6575ed50d84769024e54decfde68968be33bb266f1faa0a0fd9157e47e9, + right: 0x130c2fd7a701ec84b9ef42c9a45cb115581c268de360db13e748c1c2c62cc03, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x57a2288b799d131ce7d6c934ce288e5dcc72214871e92f25420d6cb70de6f57, + right: 0x3be816d1fe67968529d322c2d550b3968dc846a938d4878c97f3e974c17f9b, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x14f24c1f2b88d01188f4d72cfe1857668cb5507a92516cf356a618363aa369c, + right: 0x19a3203d5b1ec5a02c56f8672694f766a2a1f073430cca00362b71b19dc71f2, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x2b54c34d1145942663561aba685c1afd12e991739a30d109fdbe17ff1416f60, + right: 0x547e87abcc29a44e0f57f5bd4c9ca5bddb73a8a24ef1faf188aab963158df04, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x412b79bf0b5c3ac8eeca6ffc739aa9c48a0fb9834f9f683ef75400023547ea4, + right: 0x412022f2d1d47198766e74d76a6933348a922727170ed03c6a73b1c854bc11f, + } + ), + TrieNode::Edge( + EdgeNode { + path: 0x221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3, + length: 229, + child: 0x1fe7bef4bd2a37b56eab84508f217fd2a85694bbeb95e98049faa0de0a2011c, + } + ) + ], + contract_data: ContractData { + class_hash: 0x1cb96b938da26c060d5fd807eef8b580c49490926393a5eeb408a89f84b9b46, + nonce: 0x0, + contract_state_hash_version: 0, + storage_proof: array![ + TrieNode::Binary( + BinaryNode { + left: 0x5b1f6f4ba862f9d83fb1c6cbfc8ab6ccf8864ff40f9cd1e86b653978b7da18e, + right: 0x6a14610de840e87de4c10fca04caa9fe93f854b6e3dd528dde1eedddf0ce84, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x1e43960a3be85b1ad5a3b198617b0740b684e87a44e9e688f39cfa491cda57a, + right: 0x51ae9c0371c2f844155d26505bb26cf312e37aeae8e5610135579225c63b78e, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x418949d2696cf64b33ea5f45d97bd2b21a0a664bebf96321902a01cd3b48d2a, + right: 0x6fd4f5c829467a9ceeb891549993fb83b8003588d8c8cff156bd1c099dbc5ef, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x7d07c08fa0f20455453f16b278ca6f710553339a2dbb8f58e15925a6217643, + right: 0x47129129d16cb646a2c34f7c9c067c9acaad81b6839b6fc09e8b80c34bebde7, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x175c91990d2333c3de3f370030f901f1872a24aa5f6da397a213e2a5b0d16b9, + right: 0x65a68f50434c58e521c95a1397ed91a10eed6e0aa2c417ca08d54caf39a0708, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4849c87d07ba2a2b8349c3bf55638b549888e9c04f42220f1df86aa41483a8b, + right: 0x19f7fc3721a344be4598e7973ee3b1b5fb1451b4d7d7bab65d6f9528ad171cc, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x68eac761b78dc264977294b7d2971160597048591ddd82a566c69f084d35843, + right: 0x384b4f58bf7f2cad7d361fc4f39061e9441f61053cb92aa4ca7591c1d2ce332, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x8530109039a3265f9bed7d53935d934d8b3c243559c824f936212d82568d7, + right: 0x609f90d6f706eb20ed763dda2409b873303257a4bd21efec3f0cef4f1e1bb15, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x214a3f760450952ded394c66f9e771c743c8fc1b94408c3d75d7218e3c4ea0d, + right: 0x4acaaa512264bfad4c4fae98f7ffc61af4ab6ef12f691a93eb77498e28bd981, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x132a39f6d01334cea3f78df8fc6562de3b12ecbb59c039c04d5114dcc786e4f, + right: 0x589c451d11284e28647bd8f69cc52316340bdbb06cc8dfd3e58693521867b8f, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x283b8a927ca6f39030687e134a0fbb62581152c8c356c39398c10d6439137b4, + right: 0x26c8829289038b3fd39cbb84a77d5b581d207b02da385fd6bdb784831b7042c, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5a6263b13773bb2b02b60016825a626f4811d6f4a2015de7c6b1a34475ae518, + right: 0x74de5b7ad01a7652cb6f8bdd7eec2087063cd4c1c9774d8c571f42de2de790e, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x19dc54d0aadb395e9592f85ed9ba3766e8427c20ed1511ad626ebfbf61c3f03, + right: 0x260370da71cc1846829b69960e450b73a2f0155e2e4a9c2bee14246696c5e20, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x14e0a63dd9f386828c7af13462d186926013c4c21c0665540a7cdbaf8129998, + right: 0x22fb7449e5d36d92fedc78b6748bbd197ea244a7154b2535efa1cd83d8922ee, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4ad9584d03093e399559c74959224dbc546d4fd5645a04663717e7f26e1ae73, + right: 0x1c6e23d891ecf1b564372671373a1fb6c532be0125891e8aaafe8426e9795d8, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x9ac60824ab502ac8be539b6dfeb05a3f71b74e948388bf5eb739fa53481afd, + right: 0x696b378cb1848e77e9ceaab566a5f42dde26de2fd5cfcbaa2fd97d03aeea47, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x46a09c16ff0771585b796f48e96ddc36e7916b397c7cbd60de12618c427552d, + right: 0x12842effc2e3ad5ef995ec99f002b6540049f1368187625c08086a83523fe73, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x70854f31bd97611b9896baad3d44f7de4fc20d4ab1fd4a62fb4fa7eebb2affc, + right: 0x518745f6fb6490d53796a377b1c04923a58041d8c8063fcd6d2d3c7e7b06d19, + } + ), + TrieNode::Edge( + EdgeNode { + path: 0x3, + length: 2, + child: 0x1c5f3e73c9e969b9c5a621955d4813de68ca42a777fd4915ac5e71a73219893, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x59e2516845b39a0f0771e257685ac06e3c3f1f479825521be982162dd249b24, + right: 0x1e4a53612070bf13d7677c61cb5448713d8479d57fba3d50059227d57ba0522, + } + ), + TrieNode::Edge( + EdgeNode { + path: 0x108cd202d1472587dfe63dbf2d5ec767cbf4218b59b7ab71956780c6ee, + length: 230, + child: 0x78bc9be7c9e60005, + } + ) + ], + } + } +} + +fn total_balance_proof() -> ContractStateProof { + // func _total_supply() -> (res : Uint256): + // get_storage_var_address('_total_supply') + // storage_address = 0x37a9774624a0e3e0d8e6b72bd35514f62b3e8e70fbaff4ed27181de4ffd4604; + // ./get_storage_proof 0x02f63993df97fb44439d8e2e999c8b9b51efba1eff78e5c994c709c82b442e65 \ + // 0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3 \ + // 0x37a9774624a0e3e0d8e6b72bd35514f62b3e8e70fbaff4ed27181de4ffd4604 + + ContractStateProof { + class_commitment: 0x5eed4c30c17df1a41905c9824f2a296b6f77e91f0f017290752a60fbb8f9ff7, + contract_proof: array![ + TrieNode::Binary( + BinaryNode { + left: 0x74b59299e8315ce3c9d679b0a439f8bd6d55f1f7544b98852c85c953ec57e8, + right: 0x2390819e385bb1876e077b5ed4a4bae52c0e16ae7efee4c889c3d5247f6fb60, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5ef3be75d230f16f9f62058cd51f33fe511f132400e24ede72fe931d9afcd59, + right: 0x404d825da685c12746a2b2b7089c13561135ac529a6624b848951993331de4f, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5cbf312528ca49ab9012f368994adcb85f778360c68d61ddfa94e5db04e39bf, + right: 0x4df940db2395b5a8929cf658e36b45e88431aa9b0a1513e5318d81e83af66ca, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x5e002697a7591f4cb36f024142c249493ea69f2820aae9842b085d9cd20a825, + right: 0x78e4c02f55114f6b4989788d52e2d03bd3416f720d090215a7f95d1178166c6, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4ad60a445f0a47f285861868f332f310b405acc3366a44483b534daefc4061b, + right: 0x4a3bff604eb492f216f053a8756d7c3cb2f80649c4a3fea7d5ed939b24c784c, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x316045f83427fc1a617bb370fa2b1a7a03d462b264729424f52c6ae00e1f71a, + right: 0x7ca38911fbfba4481ea60591a97b01861825c1f908dd7fc3141192b79b55d43, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x17bf798cac821552f0e3d804dd9876e286c63d64d64aca19aea00ea9110ff58, + right: 0x33b2593a0e40d4ed0ddb6d8b7b824a2bde13062dc405c2394a8a797c35b4b32, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x1a78b3285e1f816ec7fdeeecbd7de855c3fe50e49cb9d294c0fbe698a8f0964, + right: 0x737aebdf31cbf55171144bd658e0e82862541b0af78d3241e13de77015f1ce3, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x7267f91ecdc6e579864613a406750bc80363a2be5ff863f020e5531eb8d947a, + right: 0x65bcc933abbb3c71cf3edd535204f34eb58a7329a53688039733420571f45fc, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0xac490c5cda65c26fe042c08d9bec48f399db1b0c551eb3fcbcf5fc51643beb, + right: 0x574edd4ea6655ada56844d7b7797af4fb66fa8e86361ee201d817de885ab751, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x54407ae16b65fd67d64fc8528f7240cd4c6914041dd9e3bf7c56cbab58eb42e, + right: 0x5e7d51e63c8c33f864418dd61e720cfcda9363d9b6b1c5de11f68b2d0a9a448, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4550dba3e8b473bc2b4cc6c99c43ec90864930f4ec06affb267f24ad16df0b5, + right: 0x545515cd797a277cdb88ab7efaa63ea979220696e51c6173de23984ff1746c4, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x14fa907e7e9633b6f3dcabfe07e8dac02e0aea480949bfd0f8dea13ecb5c50c, + right: 0x5448b1aac9acedab60b5401d6330bfabd397f1086ab42948ed1fa81e38a2157, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x1139a46c5e89fbcc483b8726d3e7707122b57ccdf955df4216cb1a93ffffd7a, + right: 0x6729ff6fec2dfcc6535bc4eea26fc4eb65e0285d4f8ae0fe6be4c343d9bb720, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x3d7dcabc79ce522ffb88b167edfd51896a6430a456250290f2ac1cdbe6572b3, + right: 0x990164dd962c5d48dd9a98cd8845bfdd483cbc07bbbfcd2c19daee84992e28, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x59cc416528b7228ed0064a393ed60462f5e556d5a236f7b94ea8d510641cd64, + right: 0x325c342f00e73f97c8a1ff2462c754dbb27b967223954f690e1d069e5088599, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x3c976052cb6c461679e159c1b711e8d0261d240745931ea399edf389848f99d, + right: 0x4f65e0c2b833c972c02ad133e6aa152a6e9d15bca277c2b163bc09c8b2e2b1c, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x338b6575ed50d84769024e54decfde68968be33bb266f1faa0a0fd9157e47e9, + right: 0x130c2fd7a701ec84b9ef42c9a45cb115581c268de360db13e748c1c2c62cc03, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x57a2288b799d131ce7d6c934ce288e5dcc72214871e92f25420d6cb70de6f57, + right: 0x3be816d1fe67968529d322c2d550b3968dc846a938d4878c97f3e974c17f9b, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x14f24c1f2b88d01188f4d72cfe1857668cb5507a92516cf356a618363aa369c, + right: 0x19a3203d5b1ec5a02c56f8672694f766a2a1f073430cca00362b71b19dc71f2, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x2b54c34d1145942663561aba685c1afd12e991739a30d109fdbe17ff1416f60, + right: 0x547e87abcc29a44e0f57f5bd4c9ca5bddb73a8a24ef1faf188aab963158df04, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x412b79bf0b5c3ac8eeca6ffc739aa9c48a0fb9834f9f683ef75400023547ea4, + right: 0x412022f2d1d47198766e74d76a6933348a922727170ed03c6a73b1c854bc11f, + } + ), + TrieNode::Edge( + EdgeNode { + path: 0x221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3, + length: 229, + child: 0x1fe7bef4bd2a37b56eab84508f217fd2a85694bbeb95e98049faa0de0a2011c, + } + ) + ], + contract_data: ContractData { + class_hash: 0x1cb96b938da26c060d5fd807eef8b580c49490926393a5eeb408a89f84b9b46, + nonce: 0x0, + contract_state_hash_version: 0, + storage_proof: array![ + TrieNode::Binary( + BinaryNode { + left: 0x5b1f6f4ba862f9d83fb1c6cbfc8ab6ccf8864ff40f9cd1e86b653978b7da18e, + right: 0x6a14610de840e87de4c10fca04caa9fe93f854b6e3dd528dde1eedddf0ce84, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x520667ac8a496785d0cd5cb089b0cb29945b562e83710fc86af2efc8036c70b, + right: 0x37ac663feac78c6874c9b590da7a95c81300999b98a3e81e67e68da3ea4c0da, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x349bdf44a6242b9a59f1a2f7e80fa1ac46537ba79a87dfdc1242dd5e56c0e3d, + right: 0x4aa5bab04c0c8736256a8af971e3586fd7cf2b4c9bfcba5b0e41d6deb2c0210, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x6f80e375bf182b03a572efa3d173f5e24d24c46767b539b09d5da71a6660f30, + right: 0x3a1195997ac1a9c0916fedc1e517f898107f3b7c77a296f9a35ff81151439aa, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x2647b8aa91f2bb4e1d69f4980edd96682f598cc48cbb20dbbf936ffc377b4e, + right: 0x39e7026a6f18dd6f708a8952c7b0aacbbf1db905218054297477d8c25318568, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4e2a00cf57be57bbd118c9ab71895c7047183735ece0939e77788ec10e71012, + right: 0x41312dcf660136c32c91f58e3ee95369d19d412d64fa1ec4a23c294764bc882, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x39e3c2bf03259269187def48eb867ad895db833facb97a2f470b582d36f437b, + right: 0x39bee0562de69bee56148afe63102e5b02f90a03633490a052bce4e34c2875f, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x45db82dc29b036f35b7c66fc8dd13697daf088bbc927d25ca4cc9f1817a0089, + right: 0x52deda355e21ebb91d0c9b184691a18b1839ce7955120aa7fd80a6938d56f5d, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x3e4394e2845c925b8472c7ee03cefe64c395a560bd75900088b10add7f51625, + right: 0xfb1ea9c19ce64ee5d00bb19cf5faac2872da0745a58ebf9079b2f6ff92ebda, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x7043bd6bb907453c60db302e508991260904d039f410ff97d38bd2d60ca5d75, + right: 0x76886a77ca42c2dacb8780c85afc14182b1d8e41b60f93d2599218ebd557aa7, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x6e005e3c288932475c89a0027ab76f54305e52fdf76e1276822eafdd5467a8, + right: 0x6135e891729cd592e022cf5d41eff16aa7961d989e4d825f68c580578c4570, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x7fff05dc95866ab7824f986bf1397186f762e29492dd7a8acbe40f50f1d27ee, + right: 0x1bdf43fbab99379bdda54fbf68f8559e53e1d8a06856335bbe90c007de0e41b, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x6ab794547fdc0c0df16d2b50d0888e9879e7d65f09b472d760035a9a2e20902, + right: 0x53fcb3fd666b04e0a47c1217ad463562592c6b9667e6ce6170b29f4caeb04f4, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x6635812b09537421c48fe6a76a0879044797b1f29dd64575cd43b033fcd5f1c, + right: 0x4e330b33f2a61e74481081c85f43cc04d16aa379f2b5a78c9b18759a49fcff1, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x2958f83f705b6e469df752f5b3164daa32cf7b5ecb5f70d45ca1414ff506a07, + right: 0xfb5f65d6e84d9fcff953b7104fdd986deb87abf0d6718b6e428ba97a21238d, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x792f8b2826c608d0505c83ce3f3856aed9e0e5fe4ee000f5bfefc2d1ffbc61c, + right: 0x8677c2610258f9e59456fcae3d2308fb62f1d402c2dabf849dbd756ccef424, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x1701d58385b31302c77262266e4111e079c00344b991941fedd06dbd01d9396, + right: 0x7f986636ccc6810f859e062b93905d7ff21ac6bd902de9ee8c0701d623793fd, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x4c9bfbf1f1530a1af3243e828cc0d7985b54c8c1f0c8b8b5189e49d5040068b, + right: 0x1b10ed0481c3d5d12f0a2eaa7a67078550c2654cbafc33763802a90cf3203b3, + } + ), + TrieNode::Binary( + BinaryNode { + left: 0x2d0cea7e0eec26969fff766b2e37d001249103fc62a621a3ff6692325fc1096, + right: 0xea434f6ac5a646ee23bfe12099993ea0626f4d7aa7598fe0933cfc3ce140f7, + } + ), + TrieNode::Edge( + EdgeNode { + path: 0x74624a0e3e0d8e6b72bd35514f62b3e8e70fbaff4ed27181de4ffd4604, + length: 232, + child: 0x275077fb6c1316d13a907, + } + ) + ], + } + } +} diff --git a/src/storage/src/lib.cairo b/src/storage/src/lib.cairo index d58e032f..15b64dee 100644 --- a/src/storage/src/lib.cairo +++ b/src/storage/src/lib.cairo @@ -2,4 +2,3 @@ mod list; #[cfg(test)] mod tests; -