-
Notifications
You must be signed in to change notification settings - Fork 13
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
proofs: remove post-values in Multiproof #297
Conversation
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
// TODO: see if this can be captured at the witness | ||
// level, like it used to. | ||
for _, key := range keys { | ||
// WORKAROUND: the post trie would normally not | ||
// need to be searched for keys, as all of them | ||
// were resolved during block execution. | ||
// But since the prefetcher isn't currently used | ||
// with verkle, the values that are read but not | ||
// written to, are not resolved as they are read | ||
// straight from the snapshot. They must be read | ||
// in order to build the proof. | ||
_, err = vtrpost.GetWithHashedKey(key) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
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.
This shouldn't be needed from the previous PR that we properly use the resolver
in the GetElementsForProof
. Now, this is even more true since we don't do that for proof generation so this should be safe.
I can't test it directly since this code path only works in real proof generation, so let's be aware the next time we update nodes in Kaustinen.
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.
well if it fails, and looking at it and the fact that it doesn't in sync mode, I'm comfortable enough merging that. If it fails, we'll figure it out fast enough after relaunch.
@@ -518,7 +518,7 @@ func TestProcessVerkle(t *testing.T) { | |||
//f.Write(buf.Bytes()) | |||
//fmt.Printf("root= %x\n", chain[0].Root()) | |||
// check the proof for the last block | |||
err := trie.DeserializeAndVerifyVerkleProof(proofs[1], chain[0].Root().Bytes(), keyvals[1]) | |||
err := trie.DeserializeAndVerifyVerkleProof(proofs[1], chain[0].Root().Bytes(), chain[1].Root().Bytes(), keyvals[1]) |
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.
The DeserializeAndVerifyVerkleProof
now also receives the expected post-tree root.
This is because now we do an extra check to see if the reconstructed post-state tree root, matches the block state root.
This must be true. If it's false, the block is invalid (or there's a bug in post-tree reconstruction).
go.mod
Outdated
github.com/gballet/go-verkle v0.1.1-0.20231020124853-d124d1998b1a | ||
github.com/gballet/go-verkle v0.1.1-0.20231024193227-1127148c02ea |
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.
Pointing to latest commit in ethereum/go-verkle#407
When that PR is merged, I'll update this PR to point to master.
|
||
var others set = set{} // Mark when an "other" stem has been seen | ||
func DeserializeAndVerifyVerkleProof(vp *verkle.VerkleProof, preStateRoot []byte, postStateRoot []byte, statediff verkle.StateDiff) error { | ||
// TODO: check that `OtherStems` have expected length and values. |
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.
This is something that we should do. This prob needs to be done in PreStateTreeFromProof(...)
. The pre-state tree reconstruction should consume exactly all elements in OtherStems
. If some extra value isn't used, then the proof should be considered incorrect (IMHO).
This is unrelated with all this post-state change; just something I realized that I believe was the original idea of this deleted code in L339-349 & L356-359 (all that code wasn't doing anything).
To do this extra check, we don't need that code, so I'm suggesting here to be removed (since it's currently not doing anything).
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.
sure yes we should add this, in another PR if you prefer.
// TODO: this is necessary to verify that the post-values are the correct ones. | ||
// But all this can be avoided with a even faster way. The EVM block execution can | ||
// keep track of the written keys, and compare that list with this post-values list. | ||
// This can avoid regenerating the post-tree which is somewhat expensive. | ||
posttree, err := verkle.PostStateTreeFromStateDiff(pretree, statediff) | ||
if err != nil { | ||
return fmt.Errorf("error rebuilding the post-tree from proof: %w", err) | ||
} | ||
regeneratedPostTreeRoot := posttree.Commitment().Bytes() | ||
if !bytes.Equal(regeneratedPostTreeRoot[:], postStateRoot) { | ||
return fmt.Errorf("post tree root mismatch: %x != %x", regeneratedPostTreeRoot, postStateRoot) | ||
} |
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.
As I mentioned in Matrix; just re-explaining in this TODO.
Something to explore in the future after doing more measurements.
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.
but wait, root computation will be performed in IntermediateRoot
and there is a check that it matches the header in the block. If you already check that all written values are the same as were found during execution, there is no need to compute/check the root here.
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.
That's exactly what I describe in my TODO above saying:
// TODO: this is necessary to verify that the post-values are the correct ones.
// But all this can be avoided with a even faster way. The EVM block execution can
// keep track of the written keys, and compare that list with this post-values list.
// This can avoid regenerating the post-tree which is somewhat expensive.
If we do that, we can avoid it.
Or maybe are you referring to something different?
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.
no that's what I meant: let's do that, so that we don't have to recompute the root
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.
LGTM. Let's wait for the go-verkle PR to be merged.
Left one comment about the root commitment verification that we can discuss in matrix.
|
||
var others set = set{} // Mark when an "other" stem has been seen | ||
func DeserializeAndVerifyVerkleProof(vp *verkle.VerkleProof, preStateRoot []byte, postStateRoot []byte, statediff verkle.StateDiff) error { | ||
// TODO: check that `OtherStems` have expected length and values. |
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.
sure yes we should add this, in another PR if you prefer.
// TODO: this is necessary to verify that the post-values are the correct ones. | ||
// But all this can be avoided with a even faster way. The EVM block execution can | ||
// keep track of the written keys, and compare that list with this post-values list. | ||
// This can avoid regenerating the post-tree which is somewhat expensive. |
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.
let's do it, unless it makes the PR so much more complex, that it makes sense to split it?
// TODO: this is necessary to verify that the post-values are the correct ones. | ||
// But all this can be avoided with a even faster way. The EVM block execution can | ||
// keep track of the written keys, and compare that list with this post-values list. | ||
// This can avoid regenerating the post-tree which is somewhat expensive. | ||
posttree, err := verkle.PostStateTreeFromStateDiff(pretree, statediff) | ||
if err != nil { | ||
return fmt.Errorf("error rebuilding the post-tree from proof: %w", err) | ||
} | ||
regeneratedPostTreeRoot := posttree.Commitment().Bytes() | ||
if !bytes.Equal(regeneratedPostTreeRoot[:], postStateRoot) { | ||
return fmt.Errorf("post tree root mismatch: %x != %x", regeneratedPostTreeRoot, postStateRoot) | ||
} |
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.
but wait, root computation will be performed in IntermediateRoot
and there is a check that it matches the header in the block. If you already check that all written values are the same as were found during execution, there is no need to compute/check the root here.
// TODO: see if this can be captured at the witness | ||
// level, like it used to. | ||
for _, key := range keys { | ||
// WORKAROUND: the post trie would normally not | ||
// need to be searched for keys, as all of them | ||
// were resolved during block execution. | ||
// But since the prefetcher isn't currently used | ||
// with verkle, the values that are read but not | ||
// written to, are not resolved as they are read | ||
// straight from the snapshot. They must be read | ||
// in order to build the proof. | ||
_, err = vtrpost.GetWithHashedKey(key) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
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.
well if it fails, and looking at it and the fact that it doesn't in sync mode, I'm comfortable enough merging that. If it fails, we'll figure it out fast enough after relaunch.
Signed-off-by: Ignacio Hagopian <[email protected]>
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.
LGTM
* update proof generation Signed-off-by: Ignacio Hagopian <[email protected]> * simplification and comment Signed-off-by: Ignacio Hagopian <[email protected]> * update go-verkle Signed-off-by: Ignacio Hagopian <[email protected]> --------- Signed-off-by: Ignacio Hagopian <[email protected]>
* update proof generation Signed-off-by: Ignacio Hagopian <[email protected]> * simplification and comment Signed-off-by: Ignacio Hagopian <[email protected]> * update go-verkle Signed-off-by: Ignacio Hagopian <[email protected]> --------- Signed-off-by: Ignacio Hagopian <[email protected]>
* update proof generation Signed-off-by: Ignacio Hagopian <[email protected]> * simplification and comment Signed-off-by: Ignacio Hagopian <[email protected]> * update go-verkle Signed-off-by: Ignacio Hagopian <[email protected]> --------- Signed-off-by: Ignacio Hagopian <[email protected]>
This PR does some client-side changes to adjust proofs to not include post-state values.
It depends on ethereum/go-verkle#407 being merged.