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

eth/tracers/live: run supply tests off of generated artifacts #30451

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
}
if bc.logger != nil && bc.logger.OnGenesisBlock != nil {
if block := bc.CurrentBlock(); block.Number.Uint64() == 0 {
alloc, err := getGenesisState(bc.db, block.Hash())
alloc, err := GetGenesisState(bc.db, block.Hash())
if err != nil {
return nil, fmt.Errorf("failed to get genesis state: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func flushAlloc(ga *types.GenesisAlloc, triedb *triedb.Database) (common.Hash, e
return root, nil
}

func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.GenesisAlloc, err error) {
func GetGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.GenesisAlloc, err error) {
blob := rawdb.ReadGenesisStateSpec(db, blockhash)
if len(blob) != 0 {
if err := alloc.UnmarshalJSON(blob); err != nil {
Expand Down
10 changes: 5 additions & 5 deletions eth/catalyst/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa
if params.BeaconRoot != nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("unexpected beacon root"))
}
switch api.eth.BlockChain().Config().LatestFork(params.Timestamp) {
switch api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) {
case forks.Paris:
if params.Withdrawals != nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("withdrawals before shanghai"))
Expand All @@ -224,7 +224,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
if params.BeaconRoot == nil {
return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
}
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Prague {
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
}
}
Expand Down Expand Up @@ -477,7 +477,7 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun"))
}
if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) == forks.Shanghai {
if params.Withdrawals == nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai"))
}
Expand Down Expand Up @@ -514,7 +514,7 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
}

if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Cancun {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads"))
}
return api.newPayload(params, versionedHashes, beaconRoot)
Expand Down Expand Up @@ -542,7 +542,7 @@ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHas
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun"))
}

if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague {
if api.eth.BlockChain().Config().LatestPostLondonFork(params.Timestamp) != forks.Prague {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV4 must only be called for prague payloads"))
}
return api.newPayload(params, versionedHashes, beaconRoot)
Expand Down
141 changes: 141 additions & 0 deletions eth/tracers/live/supply_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package live

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"os"
"path"
"path/filepath"
"strings"
"testing"
"unicode"

"github.com/ethereum/go-ethereum/tests"
)

type blockTest struct {
bt *tests.BlockTest
Expected []supplyInfo `json:"expected"`
}

func (bt *blockTest) UnmarshalJSON(data []byte) error {
tmp := make(map[string]json.RawMessage)
if err := json.Unmarshal(data, &tmp); err != nil {
return err
}
if err := json.Unmarshal(tmp["expected"], &bt.Expected); err != nil {
return err
}
if err := json.Unmarshal(data, &bt.bt); err != nil {
return err
}
return nil
}

// The tests have been filled using the executable at
// eth/tracers/live/tests/supply_filler.go.
func TestSupplyTracerBlockchain(t *testing.T) {
dirPath := filepath.Join("tests", "supply")
files, err := os.ReadDir(dirPath)
if err != nil {
t.Fatalf("failed to retrieve tracer test suite: %v", err)
}
for _, file := range files {
if !strings.HasSuffix(file.Name(), ".json") {
continue
}
file := file // capture range variable
var testcases map[string]*blockTest
var blob []byte
// Tracer test found, read if from disk
if blob, err = os.ReadFile(filepath.Join(dirPath, file.Name())); err != nil {
t.Fatalf("failed to read testcase: %v", err)
}
if err := json.Unmarshal(blob, &testcases); err != nil {
t.Fatalf("failed to parse testcase %s: %v", file.Name(), err)
}
for testname, test := range testcases {
t.Run(fmt.Sprintf("%s/%s", camel(strings.TrimSuffix(file.Name(), ".json")), testname), func(t *testing.T) {
t.Parallel()

traceOutputPath := filepath.ToSlash(t.TempDir())
traceOutputFilename := path.Join(traceOutputPath, "supply.jsonl")
// Load supply tracer
tracer, err := newSupply(json.RawMessage(fmt.Sprintf(`{"path":"%s"}`, traceOutputPath)))
if err != nil {
t.Fatalf("failed to create tracer: %v", err)
}
if err := test.bt.Run(false, "path", false, tracer, nil); err != nil {
t.Errorf("failed to run test: %v\n", err)
}
// Check and compare the results
file, err := os.OpenFile(traceOutputFilename, os.O_RDONLY, 0666)
if err != nil {
t.Fatalf("failed to open output file: %v", err)
}
defer file.Close()

var (
output []supplyInfo
scanner = bufio.NewScanner(file)
)
for scanner.Scan() {
blockBytes := scanner.Bytes()
var info supplyInfo
if err := json.Unmarshal(blockBytes, &info); err != nil {
t.Fatalf("failed to unmarshal result: %v", err)
}
output = append(output, info)
}
if len(output) != len(test.Expected) {
fmt.Printf("output: %v\n", output)
t.Fatalf("expected %d supply infos, got %d", len(test.Expected), len(output))
}
for i, expected := range test.Expected {
compareAsJSON(t, expected, output[i])
}
})
}
}
}

// camel converts a snake cased input string into a camel cased output.
func camel(str string) string {
pieces := strings.Split(str, "_")
for i := 1; i < len(pieces); i++ {
pieces[i] = string(unicode.ToUpper(rune(pieces[i][0]))) + pieces[i][1:]
}
return strings.Join(pieces, "")
}

func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) {
want, err := json.Marshal(expected)
if err != nil {
t.Fatalf("failed to marshal expected value to JSON: %v", err)
}
have, err := json.Marshal(actual)
if err != nil {
t.Fatalf("failed to marshal actual value to JSON: %v", err)
}
if !bytes.Equal(want, have) {
t.Fatalf("incorrect supply info:\nexpected:\n%s\ngot:\n%s", string(want), string(have))
}
}
87 changes: 87 additions & 0 deletions eth/tracers/live/tests/supply/eip1559_burn.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"eip1559_burn_grayGlacier": {
"blocks": [
{
"BlockHeader": {
"BaseFeePerGas": "0x342770c0",
"BlobGasUsed": null,
"Bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"Coinbase": "0x0100000000000000000000000000000000000000",
"Difficulty": "0x20000",
"ExcessBlobGas": null,
"ExtraData": "0x",
"GasLimit": "0x47e7c4",
"GasUsed": "0x5208",
"Hash": "0x7891c11e0cc121c578c62c4b42622b909f4ded1a66fea03336c303e6bc8d6f88",
"MixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Nonce": "0x0000000000000000",
"Number": "0x1",
"ParentBeaconBlockRoot": null,
"ParentHash": "0xc4265421181cafc43e4b97ae4f21530e37e00320f219a13311482c9c552bcdc7",
"ReceiptTrie": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa",
"StateRoot": "0x208dc296c4dc37b673a99aed4837174a2ed7f5380ad802d5aed0295e6795241d",
"Timestamp": "0xa",
"TransactionsTrie": "0x4ff793bd96fb3d8d186476e59a5118de9f1813b3f22bd8a64875a535422ac62f",
"UncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"WithdrawalsRoot": null
},
"ExpectException": "",
"Rlp": "0xf9026cf901faa0c4265421181cafc43e4b97ae4f21530e37e00320f219a13311482c9c552bcdc7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a0208dc296c4dc37b673a99aed4837174a2ed7f5380ad802d5aed0295e6795241da04ff793bd96fb3d8d186476e59a5118de9f1813b3f22bd8a64875a535422ac62fa0f78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c48252080a80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000084342770c0f86cb86a02f86701800285012a05f20082520894000000000000000000000000000000000000aaaa8080c001a083b46f9cdfcb2c087934d9ae79eedeaa53df39b73c58b7cba5c77d69039bdc64a05af6144d3123f5b9850f9c40fc4b8ce02bf4782f6d6bca3f88e553689d66480bc0",
"UncleHeaders": null
}
],
"expected": [
{
"issuance": {
"genesisAlloc": "0xde0b6b3a7640000"
},
"blockNumber": 0,
"hash": "0xc4265421181cafc43e4b97ae4f21530e37e00320f219a13311482c9c552bcdc7",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"issuance": {
"reward": "0x1bc16d674ec80000"
},
"burn": {
"1559": "0x10b643590600"
},
"blockNumber": 1,
"hash": "0x7891c11e0cc121c578c62c4b42622b909f4ded1a66fea03336c303e6bc8d6f88",
"parentHash": "0xc4265421181cafc43e4b97ae4f21530e37e00320f219a13311482c9c552bcdc7"
}
],
"genesisBlockHeader": {
"BaseFeePerGas": "0x3b9aca00",
"BlobGasUsed": null,
"Bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"Coinbase": "0x0000000000000000000000000000000000000000",
"Difficulty": "0x20000",
"ExcessBlobGas": null,
"ExtraData": "0x",
"GasLimit": "0x47e7c4",
"GasUsed": "0x0",
"Hash": "0xc4265421181cafc43e4b97ae4f21530e37e00320f219a13311482c9c552bcdc7",
"MixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Nonce": "0x0000000000000000",
"Number": "0x0",
"ParentBeaconBlockRoot": null,
"ParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ReceiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"StateRoot": "0x9f88be00eee1114edfd9372f52560aab3980a142efe8b5b39a09644075084275",
"Timestamp": "0x0",
"TransactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"UncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"WithdrawalsRoot": null
},
"lastblockhash": "7891c11e0cc121c578c62c4b42622b909f4ded1a66fea03336c303e6bc8d6f88",
"network": "GrayGlacier",
"postState": {},
"pre": {
"0x71562b71999873db5b286df957af199ec94617f7": {
"balance": "0xde0b6b3a7640000"
}
},
"sealEngine": ""
}
}
87 changes: 87 additions & 0 deletions eth/tracers/live/tests/supply/genesis_alloc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"genesis_alloc_grayGlacier": {
"blocks": [
{
"BlockHeader": {
"BaseFeePerGas": "0x342770c0",
"BlobGasUsed": null,
"Bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"Coinbase": "0x0100000000000000000000000000000000000000",
"Difficulty": "0x20000",
"ExcessBlobGas": null,
"ExtraData": "0x",
"GasLimit": "0x47e7c4",
"GasUsed": "0x0",
"Hash": "0x37bb7e9b45f4fb7b311abb5f815e3e00d3382d83a2c39b9b0bd22b717566cd04",
"MixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Nonce": "0x0000000000000000",
"Number": "0x1",
"ParentBeaconBlockRoot": null,
"ParentHash": "0xbcc9466e9fc6a8b56f4b29ca353a421ff8b51a0c1a58ca4743b427605b08f2ca",
"ReceiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"StateRoot": "0x98d03dd72cdfee5c55acc619a1f1bcb1be6d1a10b25b512e7c4e4c4413357940",
"Timestamp": "0xa",
"TransactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"UncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"WithdrawalsRoot": null
},
"ExpectException": "",
"Rlp": "0xf901fdf901f8a0bcc9466e9fc6a8b56f4b29ca353a421ff8b51a0c1a58ca4743b427605b08f2caa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940100000000000000000000000000000000000000a098d03dd72cdfee5c55acc619a1f1bcb1be6d1a10b25b512e7c4e4c4413357940a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018347e7c4800a80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000084342770c0c0c0",
"UncleHeaders": null
}
],
"expected": [
{
"issuance": {
"genesisAlloc": "0x1bc16d674ec80000"
},
"blockNumber": 0,
"hash": "0xbcc9466e9fc6a8b56f4b29ca353a421ff8b51a0c1a58ca4743b427605b08f2ca",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
},
{
"issuance": {
"reward": "0x1bc16d674ec80000"
},
"blockNumber": 1,
"hash": "0x37bb7e9b45f4fb7b311abb5f815e3e00d3382d83a2c39b9b0bd22b717566cd04",
"parentHash": "0xbcc9466e9fc6a8b56f4b29ca353a421ff8b51a0c1a58ca4743b427605b08f2ca"
}
],
"genesisBlockHeader": {
"BaseFeePerGas": "0x3b9aca00",
"BlobGasUsed": null,
"Bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"Coinbase": "0x0000000000000000000000000000000000000000",
"Difficulty": "0x20000",
"ExcessBlobGas": null,
"ExtraData": "0x",
"GasLimit": "0x47e7c4",
"GasUsed": "0x0",
"Hash": "0xbcc9466e9fc6a8b56f4b29ca353a421ff8b51a0c1a58ca4743b427605b08f2ca",
"MixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"Nonce": "0x0000000000000000",
"Number": "0x0",
"ParentBeaconBlockRoot": null,
"ParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"ReceiptTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"StateRoot": "0x4eaed1ec95373a6cad785d6b2506606a2c19e2e7c6d7faf4bab3472c21861b27",
"Timestamp": "0x0",
"TransactionsTrie": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"UncleHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"WithdrawalsRoot": null
},
"lastblockhash": "37bb7e9b45f4fb7b311abb5f815e3e00d3382d83a2c39b9b0bd22b717566cd04",
"network": "GrayGlacier",
"postState": {},
"pre": {
"0x703c4b2bd70c169f5717101caee543299fc946c7": {
"balance": "0xde0b6b3a7640000"
},
"0x71562b71999873db5b286df957af199ec94617f7": {
"balance": "0xde0b6b3a7640000"
}
},
"sealEngine": ""
}
}
Loading
Loading