-
Notifications
You must be signed in to change notification settings - Fork 153
core, trie: unify keccaking #598
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
base: master
Are you sure you want to change the base?
Conversation
tsahee
left a comment
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.
So.. after a lot more thinking and reading, I have yet another conclusion.
At least some of what they're currently doing is very intentional and could actualy improve performance for a native node. See for example this PR in geth that reduces allocations by introducing hashTo: ethereum/go-ethereum#30743
I think that using an existing hasher, and certainly existing buffers, could improve performance and we don't want to give up on that.
So what I suggest is something like:
create in crypto package a new function called NewLegacyKeccak256.
This function, in non-wasm mode will simply call sha3.NewLegacyKeccak256
In wasm mode, this will return a a special struct that implements crypto KeccakState interface, and just stores all written buffers internally on a write, and on a read calls Keccak256Hash on it's internal buffer.
Then, in places we need to - (including inside crypto package) - replace calls to sha3.NewLegacyKeccak256 with calls to crypto.NewLegacyKeccak256.
This will not change what happends in native mode, and will allow us to unify and use precompile in wasm mode.
| "github.com/ethereum/go-ethereum/trie" | ||
| "github.com/ethereum/go-ethereum/triedb" | ||
| "github.com/olekukonko/tablewriter" | ||
| "github.com/urfave/cli/v2" |
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.
could we avoid these (and similar import-order-only) changes so they won't turn up in future merges?
| // Inject all the MPT trie nodes into the ephemeral database | ||
| for node := range w.State { | ||
| blob := []byte(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.
these as well
Context
Keccak hashing algorithm can be used in two ways: (1) as a one-shot hash function (we are just interested in hash of the data that we already have in full) or (2) as a cryptographic sponge (for cases where we don't know all the data to be hashed yet, we need some intermediate hashes, etc.)
From the caller perspective, (1) is a completely stateless process, but (2) requires keeping some state.
The
cryptopackage exposesKeccak256Hash()andKeccak256()functions realizing (1) andNewKeccakState()for (2).Problem
There are ~20 places where we use stateful approach (2) for (1). In other words, we:
NewKeccakState()to create the sponge stateWrite(),Read(),Sum())whereas we could (and should) just use
Keccak256()utility.HOWEVER, on the other hand, we want to keep diff between our fork and upstream repo as small as possible.
Motivation
When running geth within ZK VM (like SP1) it is highly beneficial to outsource heavy computation (like Keccak) to the dedicated VM precompiles. By removing all unnecessarily stateful hashing and reusing the
Keccak256Hash()andKeccak256()utilities, it is way easier to replace all keccak invocations than to worry that some of them will persist in this strange form.Proposed changes
Use stateless keccaking only in those places that are accessible by
replay.wasm:trie/andcore/.Testing method
In the history of this branch (and its nitro companion) you will find that I added
panicto every place with 'incorrect' keccaking. Then I was running nitro system tests fromblock_validator_test.go. This way I confirmed what @tsahee anticipated - the only required changes are intrie/andcore/.pulled in by OffchainLabs/nitro#4128
closes NIT-4123
upstream ethereum/go-ethereum#33222 (in a bit extended version) was rejected as non-essential