gballet / multiproof-rs Goto Github PK
View Code? Open in Web Editor NEWA rust implementation of Alexey Akhunov's multiproof algorithm
License: Apache License 2.0
A rust implementation of Alexey Akhunov's multiproof algorithm
License: Apache License 2.0
Currently instructions are RLP-encoded like other data structures. That's not strictly necessary as after reading each opcode (1 byte) we'd know how many bytes of data to read for that opcode. So it could be a simple flat encoding of the opcodes and their operands without any metadata. This would eliminate the need for decoding them first on the verifier's side. This is also what @cdetrio is doing in turbo-mpas.
I could start working on a PR if you think this makes sense.
In make_multiproof
I think the goal had been to truncate keys of keyvals
when parsing an Extension
, but the key is simply being cloned:
Lines 492 to 499 in 269211e
Leaves are sent in the multiproof slightly different than how they are actually stored in the trie. The difference lies in the key. In the multiproof the first part of a leaf is the full path from root to leaf, instead of the partial path from previous node to leaf. The LEAF
opcode has an operand digit
which specifies how to get this partial path by cutting a prefix of the full path.
This incurs some overhead on the verifier. If the leaf was sent "normally" verifier could simply hash it without any modifications. But now, they have to decode the leaf, decode hex prefix of key, split it, encode via hex prefix, encode RLP and then hash.
My question is what's the trade-off here? what will we lose if we send leaves "normally" and not send the full path as their keys?
We use Keccak256 in an Eth1 context, but future Eth1x and Eth2 evolutions might make us prefer e.g. blake2 or anything else. The encryption-related code should be made a trait.
This is more related to an EE wanting to do token transfers using this multiproof algorithm. I'm not sure if it makes sense to merge it in the repo.
EE receives an array of txes which include among other things a signature from sender and the address of the recipient. The EE also receives a multiproof. In order to make sure addresses of the sender and recipient of the tx corresponds to the leaves sent in the multiproof, the EE needs to re-construct the path to those leaves when it's verifying the multiproof. Here's my attempt at how one could do this:
addrs
with same length as leavesLEAF
add its partial path to corresponding index of addrs
, and add this index to the leaf node being pushed on stackBRANCH
, EXTENSION
or ADD
:
addrs
entry. Also add its addrs
index (for the leaf) to the node being pushed on stackrustfmt
is not available on ARM, so I can't run it. Now that the code is going to become a bit more stable, the linter in circle CI needs to be re-enabled and cargo fmt
needs to be run in nightly
mode.
Right now rebuild
will panic, make that interface a bit more user friendly by returning a Result<Node, ...>
There are currently two instructions sets for multiproof. The repository currently uses the most ancient, as the second one is still largely unspecified at this time.
It would be nice to be able to easily switch between instructions sets. To achieve this, interaction with the instruction set should be abstracted through a trait.
make_multiproof
takes as parameters the root of the trie and a list of key values (leaves). A list of keys should be sufficient and the values are not necessary. If a values different than the actual value of the leaf is passed to make_multiproof
the verifier cannot verify the proof against the pre state root because after executing the instructions it will get a different state root.
For example, if the trie has the following keys:
then the structure will be like:
root(branch(leaf([0,0]), leaf([0, 0]), empty, empty, ...)
If then make_multiproof
is called with values...
...it will fail because of the following check:
// This is the simplest case: the key that is found at this
// level in the recursion needs to match the unique one in
// the list of keys that belong to the proof.
if keys.len() != 1 {
return Err(format!(
"Expecting exactly 1 key in leaf, got {}: {:?}",
keys.len(),
keys
));
}
Instead, it should encode the fact that at most one value is present.
This is a tracker for @s1na's question on #44
These new_* methods seem to be specific to the MPT tree. Is there maybe a way in Rust to only define them on Node and then cast a Tree to a Node when these methods are needed?
AFAIK, there isn't. This being said, indeed a difference should be made, e.g. by introducing an inherited TreeWithExtension : Tree
trait.
The current hexary Patricia Tree structure used in Ethereum poses some challenges and dropping it for another more manageable structure like binary or balanced trees is often discussed.
As a result, we want to abstract all tree interactions through a trait to be able to easily change the underlying tree implementation.
Right now rebuild
returns the root Node
. In order to compute the root hash, the partial trie has to be walked down and up once. To improve the efficiency of verifiers we could either add a new opcode or change the semantic of the existing ones to allow the verifier to produce the correct hash once every instruction has been processed.
LEAF
and EXTENSION
opcodes could be modified to directly hash the node and push the hash on the stack. HASHER
just reads in a hash from the sequence and doesn't need to be modified. The only question is how to handle branches, because it's not exactly clear when all the children have been added to the branch. One simple option is to introduce a HASH
opcode which expects a branch node on top of stack and hashes it. There are other options too.
Currently if a given key has not been inserted in the trie, the proof generator throws, which makes sense for most use-cases. But there are use-cases for proving the absence of a node. A simple one would be in the context of a token transfer EE when no node has been added for the recipient. If there's no proof, EE can't be certain the recipient has no account, and additionally to add the account it needs the path to the root for that key.
Maybe we could just relax the keyvals
in the proof to also include null
s.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.