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

t8n: verkle genesis #466

Merged
merged 27 commits into from
Aug 23, 2024
Merged

Conversation

jsign
Copy link
Collaborator

@jsign jsign commented Jul 30, 2024

This PR adds support for verkle-genesis test for t8n.

jsign added 2 commits July 31, 2024 09:21
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 61b6915 to cb40b1b Compare July 31, 2024 12:21
Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 8eb1368 to ed07ef6 Compare August 2, 2024 14:50
Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from ed07ef6 to 3edbc5b Compare August 2, 2024 14:52
jsign added 3 commits August 5, 2024 09:29
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from efc592c to 246acba Compare August 6, 2024 13:24
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 246acba to 679b9b1 Compare August 6, 2024 13:28
jsign added 3 commits August 7, 2024 09:25
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch 2 times, most recently from b5c9f3c to 4201ed0 Compare August 7, 2024 13:11
Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 4201ed0 to a9ee2e2 Compare August 7, 2024 13:16
jsign added 3 commits August 7, 2024 10:22
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
* feat: tweak eest ci (matrix).

* chore: remove prev ci.
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch 2 times, most recently from fb84a46 to 93ad9d7 Compare August 13, 2024 17:05
@jsign jsign marked this pull request as ready for review August 13, 2024 17:10
jsign added 6 commits August 13, 2024 15:49
Signed-off-by: Ignacio Hagopian <[email protected]>
Signed-off-by: Ignacio Hagopian <[email protected]>
.github/workflows/spec-tests.yml Show resolved Hide resolved
chmod +x ${{ github.workspace }}/bin/evm

- name: Archive built evm
uses: actions/upload-artifact@v4
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Each run uploads the generated fixtures as artifacts. For example, see the bottom of this run.

As we chatted in TG, after everything is stabilized we should probably:

  • Make these filling CI run once per day or similar, instead of on every PR since it takes a long time to run and that can be annoying.
  • The CI to be run on each PR, should be only the "consumption" of fixed (i.e: already generated) fixtures. Running fixtures is quite fast, and also it makes sense to target a stable/tagged set of fixtures. (i.e: filling fixtures on the same branch that consume them always has a high chance of always passing. The main idea is consuming against previous fixtures to catch regressions).

In any case, we can chat when we get a stable set of fixtures and we can change a bit the CI jobs.

pip install -e ".[docs,lint,test]"
solc-select use 0.8.24 --always-install
if [ "${{ matrix.test-type }}" == "genesis" ]; then
fill --fork Verkle --output=../fixtures-${{ matrix.test-type }} -v -m blockchain_test -n auto
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

With this line we generate all "targetable" tests on a Verkle fork, that is, using a VKT for the tree which includes:

  • All the new verkle-genesis test vectors I created.
  • All existing tests previously that could be run on a VKT (i.e: tests created from Shanghai or even previous ones).

These means around 458 filled test-vectors using verkle trees.

if [ "${{ matrix.test-type }}" == "genesis" ]; then
fill --fork Verkle --output=../fixtures-${{ matrix.test-type }} -v -m blockchain_test -n auto
else
fill --from Shanghai --until EIP6800Transition --output=../fixtures-${{ matrix.test-type }} -v -m blockchain_test -n auto
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here the single state-conversion test vector is filled since we target EIP6800Transition. But also we try to fill all existing tests from Shanghai forward; this isn't strictly useful for "Verkle needs" but we're just making sure filling for previous forks keeps working (and in fact, I had to fix things in t8n to make this work again).

This fills ~605 tests. Most of them aren't entirely useful but only the state-conversion one. The usefulness of consuming those fixtures, is making sure the EL client can keep passing tests for previous forks (e.g: full sync isn't broken).

The more test the better, but probably the other 458 fixtures are much more important to catch Verkle bugs for devnet7.

pip install --upgrade pip
pip install -e ".[docs,lint,test]"
solc-select use 0.8.24 --always-install
consume direct --input=../fixtures-${{ matrix.test-type }} -n auto
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Consume all fixtures. As I mentioned in other place, I found a problem in consume direct which doesn't return !=0 if any test fails, so the CI doesn't "fail" of some test fails.

That's quite bad since that's the hole point of the CI, but Spencer will work on that to fix it. Until that happens, it might be good to "eyeball" the CI run logs and see all passed.

@@ -522,6 +553,11 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest
if err != nil {
panic(err)
}
} else {
statedb, err = state.New(mptRoot, sdb, nil)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In the case of a non-verkle (nor state-conversion) fork, we simply re-open the MPT with the mptRoot calculated before. This fixes consuming fixtures for those.

Copy link
Owner

Choose a reason for hiding this comment

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

I expect some pushback on the geth side, but we'll see. I'd prefer to be "agnostic" but they might prefer it to be obvious.

Comment on lines +577 to +578
// VerkleRoot computes the root of a VKT from a genesis alloc.
func VerkleRoot(ctx *cli.Context) error {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is a new CLI tool to help the testing framework deal with a situation I found when fixing test filling.

The testing-library uses their own code for generating the genesis block. They only have an MPT implementation, so the genesis block was always generated with a MPT root. This is wrong for verkle-genesis tests.

Until they have a pure Python impl of a Verkle Tree and its cryptography, I offered them a new CLI that can calculate this root for them in the case we're in verkle mode. Whenever there's a execution-spec codebase implemented in Python for Verkle, they can copy-paste that implementation and come back generating the genesis vector on their side (and we can remove this CLI helper). For now, this should work and unblocked us from the problem.

core/genesis.go Outdated
Comment on lines 177 to 186
sdb := database
sdb.TrieDB().WritePreimages()
snaps, err := snapshot.New(snapshot.Config{AsyncBuild: false, CacheSize: 10}, sdb.DiskDB(), sdb.TrieDB(), types.EmptyRootHash)
if err != nil {
panic(err)
}
if snaps == nil {
panic("snapshot is nil")
}
snaps.Cap(types.EmptyRootHash, 0)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is a required fix to make state-conversion fixture consumption work. For that test (and future state-conversion ones), whenever we generate the genesis block before running test-blocks we need to enable pre-image recording.

This is needed since in the block execution of overlay tree we require the preimages of previous blocks (i.e: genesis block) to iterate the MPT and do the actual conversion.

core/genesis.go Outdated Show resolved Hide resolved
contract.Gas -= in.evm.TxContext.Accesses.TouchCodeChunksRangeAndChargeGas(contractAddr[:], pc, 1, uint64(len(contract.Code)), false)
if !contract.UseGas(in.evm.TxContext.Accesses.TouchCodeChunksRangeAndChargeGas(contractAddr[:], pc, 1, uint64(len(contract.Code)), false)) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is a bug I found when filling the verkle-genesis tests. One of them made geth panic. After digging here was the cause.

The problem was that doing -= clearly can cause an integer underflow. This made geth crash later in the execution since the gas available was garbage.

The fix is simple, use the usual UseGas which does the required checks.

@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 3b4a4ed to 897ea21 Compare August 20, 2024 18:35
consensus/beacon/consensus.go Outdated Show resolved Hide resolved
core/genesis.go Outdated Show resolved Hide resolved
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 897ea21 to 38b5850 Compare August 20, 2024 18:52
@@ -148,7 +148,7 @@ func (t *BlockTest) Run(snapshotter bool, tracer vm.EVMLogger) error {
return fmt.Errorf("post state validation failed: %v", err)
}
// Cross-check the snapshot-to-hash against the trie hash
if snapshotter {
if snapshotter && false {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Remember that now we run tests with snapshots enabled? So that's the snaphsotter value, which now is always true.

Before, this if wasn't run since clearly snapshotter was always false.

So the problem here is that if I don't disable this if now, the test consumption fails. And the failure is basically that the re-generated snapshot doesn't match the underlying tree.

Unfortunately, we need to do this since in the state-conversion test the snapshot to be reconstructed actually needs to consider two trees, and not the "main active" one since it's lacking more data (i.e: things that still live in the MPT).

So I wasn't sure if it was worth the effort of trying to attempt fixing this since:

  1. I don't know if the Geth team wants to keep doing this check?
  2. This check isn't strictly necessary, since the actual test run assertion is done anyway. (i.e: checking that the generated new state root matches with the provided one, gas usage, etc... all that still is done (remember, this if wasn't run when you run without snapshots... it's more like a "are snapshots still coherent" kind of check than a "fixture run verifies" check).

I'd say we can live with this for a while, but eventually it should be fixed or maybe only skipped if the underlying tree is an Overlay Tree (if that helps).

Signed-off-by: Ignacio Hagopian <[email protected]>
@jsign jsign force-pushed the jsign-t8n-verkle-genesis-rebased branch from 38b5850 to c08f8c1 Compare August 20, 2024 18:53
@@ -119,7 +119,7 @@ func (t *BlockTest) Run(snapshotter bool, tracer vm.EVMLogger) error {
// Wrap the original engine within the beacon-engine
engine := beacon.New(ethash.NewFaker())

cache := &core.CacheConfig{TrieCleanLimit: 0}
cache := &core.CacheConfig{TrieCleanLimit: 0, Preimages: true}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is how --cache.preimages work under the hood, which is used in L127.

Signed-off-by: Ignacio Hagopian <[email protected]>
core/genesis.go Outdated Show resolved Hide resolved
Signed-off-by: Ignacio Hagopian <[email protected]>
@@ -522,6 +553,11 @@ func MakePreState(db ethdb.Database, chainConfig *params.ChainConfig, pre *Prest
if err != nil {
panic(err)
}
} else {
statedb, err = state.New(mptRoot, sdb, nil)
Copy link
Owner

Choose a reason for hiding this comment

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

I expect some pushback on the geth side, but we'll see. I'd prefer to be "agnostic" but they might prefer it to be obvious.

cmd/evm/main.go Outdated Show resolved Hide resolved
consensus/beacon/consensus.go Outdated Show resolved Hide resolved
consensus/beacon/consensus.go Show resolved Hide resolved
core/genesis.go Outdated Show resolved Hide resolved
@@ -161,7 +161,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
}

for addr, account := range *ga {
statedb.AddBalance(addr, account.Balance)
statedb.SetBalance(addr, account.Balance)
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
statedb.SetBalance(addr, account.Balance)
// TODO set back to AddBalance after rebase
statedb.SetBalance(addr, account.Balance)

Signed-off-by: Ignacio Hagopian <[email protected]>
@gballet gballet added this to the verkle-gen-devnet-7 milestone Aug 23, 2024
@gballet gballet merged commit 9b27fba into kaustinen-with-shapella Aug 23, 2024
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants