-
Notifications
You must be signed in to change notification settings - Fork 773
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 Implementation: Build out Trie Processing #3430
Conversation
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.
Had a little bit of time and quickly glanced through, nice work! left some comments on some of your questions/todos
electra.yaml
Outdated
- el_type: ethereumjs | ||
el_image: ethereumjs:local | ||
cl_type: grandine | ||
cl_image: ethpandaops/grandine:feature-electra |
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.
Doesn't seem like that should belong to this PR?
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.
It doesn't. Accidentally included and will remove.
// Index of the child pointed by the next byte in the key | ||
const childIndex = stem[this.depth] | ||
|
||
const child = this.children[childIndex] | ||
|
||
if (child instanceof LeafNode) { | ||
// TODO: Understand the intent of what cowChild is suppoded to do |
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.
cow stands for "copy-on-write". As far as I recall cowChild is used as a record to mark the children that have been modified, in order to stack the commitment updates at the end since that is way more efficient.
|
||
// TODO - Why is the leaf node set at depth + 2 instead of + 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.
newBranch.children[nextByteInExistingKey] = child | ||
child.depth += 1 | ||
|
||
const nextByteInInsertedKey = stem[this.depth + 1] | ||
if (nextByteInInsertedKey === nextByteInExistingKey) { | ||
return newBranch.insertStem(stem, values, resolver) | ||
return newBranch.insertStem(stem, values, resolver, verkleCrypto) |
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.
return newBranch.insertStem(stem, values, resolver, verkleCrypto) | |
return newBranch.insertStem(stem, values, resolver) |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files
Flags with carried forward coverage won't be shown. Click here to find out more. |
This is ready for final review. |
static fromRawNode(rawNode: Uint8Array[], depth: number): InternalNode { | ||
static fromRawNode( | ||
rawNode: Uint8Array[], | ||
depth: number, |
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.
Can we remove depth from this API?
packages/verkle/src/node/leafNode.ts
Outdated
static async create( | ||
stem: Uint8Array, | ||
values: Uint8Array[], | ||
depth: number, |
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.
Can we remove depth here too?
packages/verkle/src/node/leafNode.ts
Outdated
} | ||
|
||
static fromRawNode(rawNode: Uint8Array[], depth: number): LeafNode { | ||
static fromRawNode(rawNode: Uint8Array[], depth: number, verkleCrypto: VerkleCrypto): LeafNode { |
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.
Remove depth here?
packages/verkle/src/verkleTree.ts
Outdated
} | ||
async findPath(key: Uint8Array): Promise<Path> { | ||
this.DEBUG && this.debug(`Path (${key.length}): [${bytesToHex(key)}]`, ['FIND_PATH']) | ||
// TODO: Decide if we should allow keys longer than 31 bytes (since a verkle stem can never be longer than that) |
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.
Can we remove this Todo? We've already discussed this right?
// Calculate the index of the last matching byte in the key | ||
const matchingKeyLength = matchingBytesLength(key, child.path) | ||
const foundNode = equalsBytes(key, child.path) | ||
if (foundNode || child.path.length >= key.length || decodedNode instanceof LeafNode) { |
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.
Is the last condition necessary? If I'm thinking about this correctly, whenever the child path length is longer than the key, the found node would necessarily be a leaf node?
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.
Couldn't really dive deep into the code base this morning, so just some quick broader comment on how we want to integrate the crypto package.
But pretty cool to see this evolving so strongly, looking forward to go deeper! 🤩
@@ -2,24 +2,22 @@ import { RLP } from '@ethereumjs/rlp' | |||
|
|||
import { type VerkleNodeInterface, type VerkleNodeOptions, type VerkleNodeType } from './types.js' | |||
|
|||
import type { VerkleCrypto } from 'verkle-cryptography-wasm' |
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 should now use the import from verkle
in Util
, just opened a related issue here ethereumjs/verkle-cryptography-wasm#54
I would go as far and argue that we should also remove the verkle-cryptography-wasm
dependency from this package as well and dependency inject, and so to have this wider strategic goal over the head that this should be replaceable and also here optimally a JS implementation being used.
We then also automatically continue to evolve a generic interface around this and keep thinking about what's needed and what not (I e.g. still like the idea that we take the more hashing related parts out directly and move over to the pedersen/poseidon hash usage from Pauls libraries https://github.com/paulmillr/scure-starknet (if applicable) and with this slowly shrink down the surface of what we need to compile over into the WASM stuff.
Feels to me that there is still too much in.
Practical note: if depency injection feels a bit impractical for now for testing and the like we could also decide to do at a later stage.
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.
Ah, but the main argument for direct dependency injection (so, this would mean: having a mandatory crypto
constructor argument) is actually that we avoid having the same bundle problems again once/if we have Verkle added somewhere as a dependency.
Co-authored-by: Gabriel Rocheleau <contact@rockwaterweb.com>
packages/verkle/src/verkleTree.ts
Outdated
async put(_key: Uint8Array, _value: Uint8Array): Promise<void> { | ||
throw new Error('not implemented') | ||
// verifyKeyLength(key) | ||
// const stem = key.slice(0, 31) | ||
// this.DEBUG && this.debug(`Key: ${bytesToHex(key)}`, ['PUT']) | ||
// this.DEBUG && this.debug(`Value: ${bytesToHex(value)}`, ['PUT']) |
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.
Not a big fan of having a lot of commented out code merge into the master branch. Could we take note of this code peripherally and just re-add it in the follow-up PR? Not a major deal as this is an experimental package though
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, have stashed it locally
Foundations for a full verkle trie implementation:
VerkleTrie
class to remove unnecessary code that was borrowed fromtrie
as well asgo-verkle
InternalNode
andLeafNode
classes to make them easier to work with (e.g. commitments are updated internally when you update a value/child in the node)children
array withinInternalNode
so that each element ofchildren
stores both the commitment for that child node as well as the path to that node (which is either a partial stem - if the child node is an Internal Node, or a full stem if the child node is a Leaf Node)findPath
to use the new structure of the internal nodes described above so that walking the trie is merely a matter of retrieving the child node at each level of thepath
key provided as an input tofindPath
depth
as a property on theVerkleNode
class (since no obvious use case)