-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor storage proofs #232
Changes from all commits
aa47b63
a68dac0
49dfa32
451d71a
1cad654
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -908,81 +908,138 @@ | |
}, | ||
{ | ||
"name": "starknet_getStorageProof", | ||
"summary": "get merkle paths in one of the state tries: global state, classes, individual contract", | ||
"summary": "Get merkle paths in one of the state tries: global state, classes, individual contract. A single request can query for any mix of the three types of storage proofs (classes, contracts, and storage).", | ||
"params": [ | ||
{ | ||
"name": "class_hashes", | ||
"description": "a list of the class hashes for which we want to prove membership in the classes trie", | ||
"required": false, | ||
"schema": { | ||
"title": "classes", | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "contract_addresses", | ||
"description": "a list of contracts for which we want to prove membership in the global state trie", | ||
"required": false, | ||
"schema": { | ||
"title": "contracts", | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/ADDRESS" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "contracts_storage_keys", | ||
"description": "a list of (contract_address, storage_keys) pairs", | ||
"required": false, | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"type": "object", | ||
"properties": { | ||
"contract_address": { | ||
"$ref": "#/components/schemas/ADDRESS" | ||
}, | ||
"storage_keys": { | ||
{ | ||
"name": "block_id", | ||
"description": "The hash of the requested block, or number (height) of the requested block, or a block tag", | ||
"required": true, | ||
"schema": { | ||
"title": "Block id", | ||
"$ref": "#/components/schemas/BLOCK_ID" | ||
} | ||
}, | ||
{ | ||
"name": "class_hashes", | ||
"description": "a list of the class hashes for which we want to prove membership in the classes trie", | ||
"required": false, | ||
"schema": { | ||
"title": "classes", | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "contract_addresses", | ||
"description": "a list of contracts for which we want to prove membership in the global state trie", | ||
"required": false, | ||
"schema": { | ||
"title": "contracts", | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/ADDRESS" | ||
} | ||
} | ||
}, | ||
{ | ||
"name": "contracts_storage_keys", | ||
"description": "a list of (contract_address, storage_keys) pairs", | ||
"required": false, | ||
"schema": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/FELT" | ||
"type": "object", | ||
"properties": { | ||
"contract_address": { | ||
"$ref": "#/components/schemas/ADDRESS" | ||
}, | ||
"storage_keys": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
} | ||
}, | ||
"required": ["contract_address", "storage_keys"] | ||
} | ||
} | ||
}, | ||
"required": ["contract_address", "storage_keys"] | ||
} | ||
} | ||
} | ||
} | ||
], | ||
"result": { | ||
"name": "result", | ||
"description": "The contract's nonce at the requested state", | ||
"description": "The requested storage proofs. Note that if a requested leaf has the default value, the path to it may end in an edge node whose path is not a prefix of the requested leaf, thus effecitvely proving non-membership", | ||
"schema": { | ||
"type": "object", | ||
"properties": { | ||
"classes_proof": { | ||
"$ref": "#/components/schemas/NODE_HASH_TO_NODE_MAPPING" | ||
}, | ||
"contracts_proof": { | ||
"$ref": "#/components/schemas/NODE_HASH_TO_NODE_MAPPING" | ||
"type": "object", | ||
"properties": { | ||
"nodes": { | ||
"description": "The nodes in the union of the paths from the contracts tree root to the requested leaves", | ||
"$ref": "#/components/schemas/NODE_HASH_TO_NODE_MAPPING" | ||
}, | ||
"contract_leaves_data": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how do we know which contract corresponds to which contract leaf data here? just using the index of the contract address in the request? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 for the index, but more convenient would be add an address here as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
EDIT: actually nevermind it doesnt matter at all for this field, we can do either |
||
"type": "array", | ||
"items": { | ||
"description": "The nonce and class hash for each requested contract address, in the order in which they appear in the request. These values are needed to construct the associated leaf node", | ||
"type": "object", | ||
"properties": { | ||
"nonce": { | ||
"$ref": "#/components/schemas/FELT" | ||
}, | ||
"class_hash": { | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
}, | ||
"required": ["nonce", "class_hash"] | ||
} | ||
} | ||
}, | ||
"required": ["nodes", "contract_leaves_data"] | ||
}, | ||
"contracts_storage_proofs": { | ||
"type": "array", | ||
"items": { | ||
"$ref": "#/components/schemas/NODE_HASH_TO_NODE_MAPPING" | ||
} | ||
}, | ||
"global_roots": { | ||
"type": "object", | ||
"properties": { | ||
"contracts_tree_root": { | ||
"$ref": "#/components/schemas/FELT" | ||
}, | ||
"classes_tree_root": { | ||
"$ref": "#/components/schemas/FELT" | ||
}, | ||
"block_hash": { | ||
"description": "the associated block hash (needed in case the caller used a block tag for the block_id parameter)", | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
}, | ||
"required": ["contracts_tree_root", "classes_tree_root", "block_hash"] | ||
} | ||
}, | ||
"required": [ | ||
"classes_proof", | ||
"contracts_proof", | ||
"contracts_storage_proofs" | ||
"contracts_storage_proofs", | ||
"global_roots" | ||
] | ||
} | ||
}, | ||
"errors": [ | ||
{ | ||
"$ref": "#/components/errors/BLOCK_NOT_FOUND" | ||
}, | ||
{ | ||
"$ref": "#/components/errors/STORAGE_PROOF_NOT_SUPPORTED" | ||
} | ||
] | ||
} | ||
} | ||
], | ||
|
@@ -3634,42 +3691,53 @@ | |
"required": ["l1_gas", "l1_data_gas", "l2_gas"] | ||
}, | ||
"MERKLE_NODE": { | ||
"title": "MP node", | ||
"description": "a node in the Merkle-Patricia tree, can be a leaf, binary node, or an edge node", | ||
"oneOf": [ | ||
{ | ||
"$ref": "#/components/schemas/BINARY_NODE" | ||
}, | ||
{ | ||
"$ref": "#/components/schemas/EDGE_NODE" | ||
} | ||
] | ||
}, | ||
"BINARY_NODE": { | ||
"type": "object", | ||
"description": "an internal node whose both children are non-zero", | ||
"properties": { | ||
"path": { | ||
"type": "integer" | ||
}, | ||
"length": { | ||
"type": "integer" | ||
}, | ||
"value": { | ||
"$ref": "#/components/schemas/FELT" | ||
}, | ||
"children_hashes": { | ||
"type": "object", | ||
"description": "the hash of the child nodes, if not present then the node is a leaf", | ||
"properties": { | ||
"left": { | ||
"left": { | ||
"description": "the hash of the left child", | ||
"$ref": "#/components/schemas/FELT" | ||
}, | ||
"right": { | ||
}, | ||
"right": { | ||
"description": "the hash of the right child", | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
} | ||
}, | ||
"required": ["left", "right"] | ||
}, | ||
"EDGE_NODE": { | ||
"type": "object", | ||
"description": "represents a path to the highest non-zero descendant node", | ||
"properties": { | ||
"path": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for edge nodes: i believe the path could be 251 bit long in the worst case, which won't fit in the type "integer" i think. I think a Felt here makes sense? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now I'm using: |
||
"description": "an integer whose binary representation represents the path from the current node to its highest non-zero descendant (bounded by 2^251)", | ||
"$ref": "#/components/schemas/NUM_AS_HEX" | ||
}, | ||
"required": [ | ||
"left", | ||
"right" | ||
] | ||
} | ||
"length": { | ||
"description": "the length of the path (bounded by 251)", | ||
"type": "integer" | ||
}, | ||
"child": { | ||
"description": "the hash of the unique non-zero maximal-height descendant node", | ||
"$ref": "#/components/schemas/FELT" | ||
} | ||
}, | ||
"required": [ | ||
"path", | ||
"length", | ||
"value" | ||
] | ||
"required": ["path", "length", "child"] | ||
}, | ||
"NODE_HASH_TO_NODE_MAPPING": { | ||
"description": "a node_hash -> node mapping of all the nodes in the union of the paths between the requested leaves and the root (for each node present, its sibling is also present)", | ||
"description": "a node_hash -> node mapping of all the nodes in the union of the paths between the requested leaves and the root", | ||
"type": "array", | ||
"items": { | ||
"type": "object", | ||
|
@@ -3796,6 +3864,10 @@ | |
}, | ||
"required": ["transaction_index", "execution_error"] | ||
} | ||
}, | ||
"STORAGE_PROOF_NOT_SUPPORTED": { | ||
"code": 42, | ||
"message": "the node doesn't support storage proofs for blocks that are too far in the past" | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was curious about a very dumb edge case: When a client says that it wants a contract storage proof for a key in a specific contract, and that same contract does not appear in
contracts_proof
, just incontracts_storage_proofs
- does that mean that we have to return a proof for that contract in the contract trie anyway?if we don't that would mean that storage proof is not verifiable by itself, but maybe that's the client's fault for not putting it in the contracts_proof too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right regards verification. IMO best is to return whatever requested and no guessing how it's used on the client side