-
Notifications
You must be signed in to change notification settings - Fork 70
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
RFC: Add a way to ask for a storage proof of just the hash of a value #590
Comments
cc @cheme |
Proposal sounds good to me, just a small question, should we merge both request v2 into :
|
Or:
(probably not a correct proto syntax, but the idea is here). |
To be honest my understanding of child tries is still blurry enough that I don't have an opinion here. |
Note: Messages are defined in the #591 PR, but this issue is part of the larger light client spec. As discussed yesterday with Bhargav, he will cover this behavior there and also spec how any storage values are verified against the merkle root/nodes. |
I've updated the OP to do this except that I've adjusted the naming a bit. The naming doesn't actually matter that much, as the names aren't sent on the wire. |
You mean "It is legal for the remote to ignore, ...". As otherwise it would not work for state-version 0? (As you say yourself in the next sentence) Besides this one nitpick, it looks good to me! |
Closing in favor of w3f/PPPs#5 |
Context and motivation
In the Polkadot network, there are two kinds of nodes: full nodes, that have the storage of recent blocks, and light clients, that don't. In order for light clients to work, they need to request from full nodes the storage items that they want to access. To do so, they send a networking request.
When it receives such networking request, the full node returns a Merkle proof containing the values that have been requested.
In some situations, the light client doesn't care about the value of the storage items that it wants to access, but only their hash. What this RFC proposes is to add a way for the light client to indicate, in the networking request, that it doesn't care about the values of the storage items that it requests but only their hash. When this is the case, the full node can omit the storage values from the Merkle proof that it sends back, and thus reduce its size, sometimes considerably.
This would be helpful, for example:
:code
.:code
from a full node. By implementing this proposal, the light client could store the value of:code
on the disk and check if it is still the same as on chain instead of always downloading it.I won't go in details as to how values can be omitted from Merkle proofs, as this is a bit complicated and out of scope here, however it is important to know that in order for values to be omitted, a chain must have transitioned to the "version 1" of the trie format by switching the
state_version
field in the runtime spec to1
. If it hasn't done this, it is not possible to omit storage values, as otherwise the proof would no longer be verifiable.Chains that are still using version 0 of the trie format should still implement this proposal, but they would leave the values in the proof like is currently the case.
It is also technically possible for a chain to be in the middle of a version 0 -> version 1 trie format transition, but this isn't problematic either, as values can be left in the Merkle proof when the corresponding storage item is still at version 0.
Changes
The current Protobuf schema for the "light client requests" protocol can be found here: https://github.com/paritytech/substrate/blob/08d1b2c7846f0280aa57dc1145a2c631b12c0789/client/network/light/src/schema/light.v1.proto
This RFC suggests the following diff:
The new message (
RemoteReadRequestV2
) is similar toRemoteReadRequest
andRemoteReadChildRequestV2
, except for the fact that therepeated bytes keys
field is replaced withrepeated Key keys
.The new
Key
struct contains the key itself (what would normally be passed in therepeated bytes keys
field), but also askipValue
boolean indicating that the value of this storage item isn't important to the requester.The
skipValue
field has been defined as an optional boolean, because I expect the value to befalse
most of the time. When the value isfalse
, it is possible to omit the field entirely, saving 2 bytes. Because this only saves 2 bytes, I don't think that this greatly matters anyway.The
skipValue
field must be considered as an optimization. It is not legal for the remote to ignore this field and send back a Merkle proof that contains the value anyway. As explained above, this is necessary in order to handle version 0 of the trie format.An alternative proposal could have been to add a request-wide
skipValue
field applying to all the requested keys, instead of oneskipValue
field per key. It is unclear to me whether there is any real advantage to having one field per key, but having one field per key is a strictly more superior solution, so in doubt I have decided to go for this one.Upgrade path
The upgrade path is simple: once a version of Substrate supporting this proposal is released and widely deployed, light clients can start sending requests.
Having a request-wide
skipValue
field instead of one per field would provide more backwards-compatibility, as older nodes would simply ignore the flag. As such, light clients could start sending requests without having wait for a version supporting this proposal to be deployed. However, sending requests with this flag when no full node supports it is kind of useless.Given that a light client must already handle situations where a full node refuses to answer requests for no particular reason, having a situation where a full node doesn't answer requests because it is too old to support this proposal doesn't add any complexity to implementations.
Misc
See also the corresponding Substrate issue: paritytech/substrate#10623
The text was updated successfully, but these errors were encountered: