Skip to content
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

verkle: verkle package #2923

Merged
merged 61 commits into from
Oct 26, 2023
Merged

verkle: verkle package #2923

merged 61 commits into from
Oct 26, 2023

Conversation

gabrocheleau
Copy link
Contributor

@gabrocheleau gabrocheleau commented Jul 29, 2023

This PR adds a new package: @ethrereumjs/verkle. Similarly to the trie package, this package will implement verkle tries as specified https://notes.ethereum.org/@vbuterin/verkle_tree_eip, enabling us to create verkle tries, do operations on them, and use them to verify and generate proofs.

Notes

I've identified cryptographic primitives that we are missing for a complete implementation (based on Go's implementation here: https://github.com/gballet/go-ethereum/blob/kaustinen-with-shapella/trie/trie.go).

  • Point class. Comes from banderwagon.Element. Quite fundamental as it represents a polynominal commitment, with a number of methods used repeatedly in the implementation.
  • toFrMultiple. Implementation comes from Banderwagon's MultiMapToScalarField method.
  • Fr class. Field representation class. Comes from Banderwagon's fr.Element.
  • CommitToPoly. Comes from ipa.IPAConfig in go-ipa/ipa. (link). Used for example when creating new leaf nodes.

@gabrocheleau gabrocheleau self-assigned this Jul 29, 2023
@gabrocheleau gabrocheleau changed the title verkle: initial commit verkle: verkle package Jul 29, 2023
@codecov
Copy link

codecov bot commented Jul 29, 2023

Codecov Report

Merging #2923 (ad58ee2) into master (876e560) will decrease coverage by 0.10%.
The diff coverage is 60.71%.

Additional details and impacted files

Impacted file tree graph

Flag Coverage Δ
block 88.78% <ø> (ø)
blockchain 92.27% <ø> (ø)
client 87.60% <ø> (+0.08%) ⬆️
common 98.19% <ø> (ø)
ethash ∅ <ø> (∅)
evm 71.87% <ø> (ø)
rlp ∅ <ø> (∅)
statemanager 90.30% <ø> (ø)
trie 89.40% <ø> (-0.96%) ⬇️
tx 96.36% <ø> (ø)
util 87.57% <60.71%> (-0.70%) ⬇️
vm 75.98% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

@gabrocheleau gabrocheleau marked this pull request as ready for review October 15, 2023 16:48
Copy link
Member

@jochem-brouwer jochem-brouwer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I have given this a look (but not in-depth), some minor comments and questions.

In general regarding the structure: my first thought would be that this is great, it is essentially MPT but now with Verkle support (so I assume it would be rather "easy" (?) to swap MPT for Verkle - of course only at the start of a client not having to do transition MPT -> Verkle).

I will need to study Verkle a bit to also review the internals, since I cannot comment on that right now.

packages/client/CHANGELOG.md Outdated Show resolved Hide resolved
// Nothing has been found in diff cache, look up from disk
const valueHex = await this.db.get(keyHex, {
keyEncoding: KeyEncoding.String,
valueEncoding: ValueEncoding.String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with Verkle we use a completely new database, right? (So not related to old MPT DB). If that's the case, can we immediately use valueEncoding set to ValueEncoding.Bytes? Then we don't have to convert bytesToUnprefixedHex early on and we don't have to deal with a breaking release for the underlying database later on.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same maybe also for keys directly)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, will go with bytes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated all key/value types to Uint8Arrays (db, cache), but kept the Checkpoint keyValueMap as Map<string, Uint8Array | undefined> since Uint8Arrays can't directly be used as Map keys (since two uint8arrays are not equal even if they contain the same data)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm now reading that using Uint8Array as key for the cache (the cache uses the LRUCache package) might cause issues. I will do some testing but I think I'll revert that part, so we'd end up with:

  • A DB that uses Uint8Arrays for keys and values
  • A cache (LRU-cache) that uses string for keys and Uint8Array as values
  • A keyValueMap (Checkpoint type) that uses string as keys and Uint8Array as values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this fails:

image

So I'll switch the cache to use hexstrings for keys.

packages/verkle/src/util/lock.ts Outdated Show resolved Hide resolved
@holgerd77
Copy link
Member

Very very very cool!!! ❤️ 🤩 This looks like an extremely solid fundament already where we can further build upon! Would vote on taking this in pretty soon (this or next week)!

bytes[7] = Number((hi >> BigInt(24)) & BigInt(0xff))

return bytes
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These new helper methods look more "advanced" (lol) than our classic conversion helpers for BE! 🙂 🤔 Also love that they explicitly target already 32/64 bit e.g..

Can you say something how they compare and relate to our existing methods, e.g. performance wise? This explicit bit-length also has the nice (and eventually performance-increasing) side effect that it omits the 0-padding if I see correctly?

If these methods are better than our old ones: might it be a mid-term option to also adopt this for our BE methods?

(would like to at least high-level settle on these kind of questions before we take new methods with new naming schemes and everything into Util)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've researched this a bit, and I think we could strike a balance between high performance and readability (the current implementation is quite opaque) by using DataView to go from Uint8Arrays to ints/bigints. I'm reading that DataViews are very performant & optimized, and the methods have built-in support for BE/LE. See this reference for more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigInt64

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you mention "adopting this for our BE methods", what methods are you referring to? bytesToBigInt and bytesToInt? I can implement alternative versions using DataViews and compare performance.

Copy link
Contributor

@scorbajio scorbajio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great! I'm not sure if something like this already exists for this package, but since it is in development, something worth considering that might attract help/contributors is if we could keep an updated list of issues with an overall master tracker on work that still needs to get done.

packages/verkle/README.md Show resolved Hide resolved
packages/verkle/README.md Outdated Show resolved Hide resolved
packages/verkle/README.md Outdated Show resolved Hide resolved
packages/verkle/README.md Outdated Show resolved Hide resolved
packages/verkle/README.md Outdated Show resolved Hide resolved
Copy link
Member

@holgerd77 holgerd77 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Let's take this in and continue to refine and evolve. 🙂

@holgerd77 holgerd77 merged commit 2353bc7 into master Oct 26, 2023
41 of 44 checks passed
@holgerd77 holgerd77 deleted the verkle/verkle-package branch October 26, 2023 07:19
@jochem-brouwer
Copy link
Member

Test-verkle and test-examples runs failed on this CI and they now also fail on master + PRs (should we make these mandatory so we cannot accidentally merge if those fail? Since it is rather error-prone if two are failing, this is in some cases codecov messing up 😅 )

https://github.com/ethereumjs/ethereumjs-monorepo/actions/runs/6645612344/job/18057315347
https://github.com/ethereumjs/ethereumjs-monorepo/actions/runs/6645612366/job/18057315572

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants