-
Notifications
You must be signed in to change notification settings - Fork 246
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
Add pathfinder_getProof
RPC endpoint
#714
Comments
@pscott is this more of a feature request or do you have plans to submit a PR of your own? |
I'd like to submit a PR on my own, but thought it would be a good idea to create an issue to discuss the design around it with you guys! :) |
TL;DR: output also requires the following for a fully verifiable merkle proof, in order to link the global state root to a given contract's storage element:
Actual postLooks reasonable to me. One thing that is missing from the return object - should it not include the merkle proof for the contract root as well? This is also present in EIP-1186 in the form of the following parts of the output:
I'll explain how and what this is in StarkNet, and why it is required, below. In StarkNet the only state part verifiable for given block is the global state root (both on L1 and L2). For this to be a verifiable merkle proof we would therefore need to connect the contract's state root to this global root. Conceptually how this works is that there are two different merkle-patricia tries in StarkNet state. A global state tree - this connects the global root where each leaf contains a contract's state hash (note: not contract root). The keys in this global tree are the contract's address. A contract's state hash is a hash over the contract root, contract nonce and state hash version. And the second tree contains the contract storage values. In order to get from global root to a specific contract storage value, one therefore has to do the following:
In order for us to have a fully verifiable merkle proof, we therefore need all three of these steps to be verifiable. Your current output allows for verifying only (3). So in addition, we need a merkle proof for (1), and then for (2) we require providing all the values that take part in the hash calculation. The end user can then:
There is one further concern I have, and that is regarding the verification of the state hash (2). The calculation is:
Another question is whether we should also give the value of edit ^^ I think we need to output this reserved value as well. |
I've made some minor edits to the post above. Essentially the crossed out section on nonces, and added that I think we do need to output reserved value as well. Unclear at this stage what to name it, but we can ask starkware what this value represents. |
@Mirko-von-Leipzig Thank you so much for this answer! I'm struggling to wrap my head around starknet's storage, and your comment is really a goldmine. (btw for anyone who might be reading this one day, I would recommend reading this official doc also). I have a couple of comments / questions:
Thanks! |
|
Super useful! Thanks! I'm glad my questions were correct, it means I understood what you said in the first comment x) Will be opening a draft PR soon hopefully! :) |
I think a good PR draft starting point is to get the merkle proof working for a single tree. So no RPC, or anything else -- just an additional function to the merkle tree implementation which returns the merkle proof of a given key. Another thing to consider ito API is what happens if the contract does not exist, or the storage key does not exist. It would not be enough to simply return an error -- since this query is about proving the state of something, the caller needs to be able to verify this is true i.e. verify that indeed, the contract or storage key does not exist. What I saw somewhere in either the EIP or some Ethereum implementation was that they return a merkle proof that proves it does not exist. You return the list of nodes as close to the desired key as possible (with the final node proving non-existance because it has deviated from the key). This will necessarily end in either: a leaf node, which is not the desired key, or an edge node which deviates from the desired key's path. For simplicity, it may be best to ignore missing keys initially, until later in the PR. Up to you of course. |
pathfinder_getProof
RPC endpointpathfinder_getStorageProofs
RPC endpoint
@Mirko-von-Leipzig @pscott Great work on this. Thanks so much. I have been playing around with the output of pathfinder_getProof and format is in json. I think there is some argument for it to be instead be RLP encoded in line with the eth_getProof format. The proofs in some use cases need to be verified on-chain and json deserialization of course is not feasible there and will have to be massaged into RLP again by the client. This could also be an improvement later on but wanted to raise a question. Thanks again Scott for working on this |
I'm hesitant to mix different encoding formats just because Ethereum has done it. A counter-argument is that everyone else that is not doing onchain verification will have to now decode it again before its usuable. Does onchain verification for this type of merkle tree already exist? |
My 2cents on the matter:
My solution: allow this endpoint to have the |
I should have been clearer, my motivation is for it to be onchain friendly format, be it RLP or SSZ etc. Just a cursory search did bring up Aragon repo where its being used https://github.com/aragon/aragon-factory/blob/fbb8963509020737dd647feb726fab66e4222ffe/contracts/vocdoni/lib.sol Just like Scott mentioned there will be use cases where it needs to be verified on chain especially when transferring data between 2 different L2s directly without going through L1 which will be expensive. I think this will be a big use case in the future to transfer data between rollups directly and if the format does not need to be transformed massaged etc it will reduce developer pain/errors and possibly re-use the verifier on different chains/l2s/rollups. Errors on-chain tend to be way more expensive than off-chain and taking data directly from pathfinder_api into the verifier will help in that. |
That's a fair point. Establishing a baseline standard would be helpful ito ecosystem. I think SSZ would make more sense as its replacing RLP where possible? I'm not too informed about the trade-offs however. |
pathfinder_getStorageProofs
RPC endpointpathfinder_getProof
RPC endpoint
After thinking about it again, it seems to me that:
Given all of that, I'm in favor of keeping JSON right now, and potentially think about moving everything to SSZ (or considering having the SSZ option as output, if there is a strong case for it) :) |
@Mirko-von-Leipzig I realize now I think we also need to return the I guess technically one can always run the |
The root should always be present in the global tree's proof (unless of course the tree is empty, but that is a bit of an extreme edge case). So you can extract it from there if you want it to be an additional field? |
Hmm currently the roo tis not present in the global tree's proof. A proof looks like this for example: http://sprunge.us/M7EOWR As you can see, the first element is a Now ofc, the user can use the first node and |
Ah sorry I misread your question. Thing is, the caller / user must have the root from some other source -- otherwise all he knows is that you gave a proof for some root. He needs some way of trusting that the root is correct for the block ID he requested. i.e. he must have it already somehow. Us providing it doesn't help, just means its an untrusted value. |
Yes I agree there's not point in having the root except... when testing. Which I am doing right now haha :p |
Just wanted to give Scott a shoutout, thank you!! Fantastic job on this. And to pathfinder team for incorporating this. |
Similarly to EIP-1186, I suggest to add a
pathfinder_getProof
endpoint to pathfinder.This would allow applications like storage proofs (courtesy of our friends at herodotus) on starknet.
Specification
As part of the pathfinder (not starknet because it's not part of the formal RPC specification), an additional method called
pathfinder_getProof
should be defined as follows:patfhinder_getProof
Returns the account- and storage-values of the specified account including the Merkle-proof.
Parameters
DATA
: 1 felt - address of the account.ARRAY
- array of storage-keys which should be proven and included. See starknet_getStorageAtQUANTITY | BLOCKHASH | TAG
- integer block number / block hash / the string "latest" or "pending"Returns
Object - An object:
contractProof
:ARRAY
- Array of MerkleTree-Nodes, starting with the root of the contract, using the contract address as path to go down along the tree.contractData
: An OPTIONAL object consisting of:contractClassHash
:DATA
1 felt - Class hash. See official documentation.contractNonce
:DATA
1 felt - contract's nonce. See official documentation.root
:DATA
1 felt - Root of the contract state tree. All storage will deliver a MerkleProof starting with this root.contractStateVersion
:DATA
1 felt - represents the state version. Might be changed in the future by Starkware.storageProofs
:ARRAY
- Array of storage-entries as requested. Each entry is an array of MerkleTree-Nodes corresponding to the nodes encountered while going down the tree with usingkey
as path.Note
contractProof
will correspond to the list of nodes closest to the desired contract, thus showing that the exact contract doesn't exist. The same logic applies to storage proofs.contractData
object will be set to 0 if the contract doesn't exist.The text was updated successfully, but these errors were encountered: