dev: fix: some wsl lint issues

This commit is contained in:
marcello33 2023-06-15 12:27:20 +02:00
parent 2c87219c80
commit 3af5e435c7
145 changed files with 1488 additions and 15 deletions

View file

@ -124,6 +124,7 @@ func (b *SimulatedBackend) Commit() common.Hash {
if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil { if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
panic(err) // This cannot happen unless the simulator is wrong, fail in that case panic(err) // This cannot happen unless the simulator is wrong, fail in that case
} }
blockHash := b.pendingBlock.Hash() blockHash := b.pendingBlock.Hash()
// Using the last inserted block here makes it possible to build on a side // Using the last inserted block here makes it possible to build on a side
@ -669,6 +670,8 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
evmContext := core.NewEVMBlockContext(header, b.blockchain, nil) evmContext := core.NewEVMBlockContext(header, b.blockchain, nil)
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true}) vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
gasPool := new(core.GasPool).AddGas(math.MaxUint64) gasPool := new(core.GasPool).AddGas(math.MaxUint64)
//nolint:contextcheck
return core.ApplyMessage(vmEnv, msg, gasPool, context.Background()) return core.ApplyMessage(vmEnv, msg, gasPool, context.Background())
} }
@ -873,6 +876,7 @@ func (fb *filterBackend) GetBody(ctx context.Context, hash common.Hash, number r
if body := fb.bc.GetBody(hash); body != nil { if body := fb.bc.GetBody(hash); body != nil {
return body, nil return body, nil
} }
return nil, errors.New("block body not found") return nil, errors.New("block body not found")
} }

View file

@ -1349,6 +1349,7 @@ func TestCommitReturnValue(t *testing.T) {
testAddr := crypto.PubkeyToAddress(testKey.PublicKey) testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr) sim := simTestBackend(testAddr)
defer sim.Close() defer sim.Close()
startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64() startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64()
@ -1380,6 +1381,7 @@ func TestCommitReturnValue(t *testing.T) {
if h2 == h2fork { if h2 == h2fork {
t.Error("The block in the fork and the original block are the same block!") t.Error("The block in the fork and the original block are the same block!")
} }
if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil { if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil {
t.Error("Could not retrieve the just created block (side-chain)") t.Error("Could not retrieve the just created block (side-chain)")
} }
@ -1392,6 +1394,7 @@ func TestAdjustTimeAfterFork(t *testing.T) {
testAddr := crypto.PubkeyToAddress(testKey.PublicKey) testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
sim := simTestBackend(testAddr) sim := simTestBackend(testAddr)
defer sim.Close() defer sim.Close()
sim.Commit() // h1 sim.Commit() // h1

View file

@ -199,9 +199,11 @@ func TestUnpackAnonymousLogIntoMap(t *testing.T) {
var received map[string]interface{} var received map[string]interface{}
err := bc.UnpackLogIntoMap(received, "received", mockLog) err := bc.UnpackLogIntoMap(received, "received", mockLog)
if err == nil { if err == nil {
t.Error("unpacking anonymous event is not supported") t.Error("unpacking anonymous event is not supported")
} }
if err.Error() != "no event signature" { if err.Error() != "no event signature" {
t.Errorf("expected error 'no event signature', got '%s'", err) t.Errorf("expected error 'no event signature', got '%s'", err)
} }
@ -384,6 +386,7 @@ func TestCall(t *testing.T) {
t.Parallel() t.Parallel()
var method, methodWithArg = "something", "somethingArrrrg" var method, methodWithArg = "something", "somethingArrrrg"
tests := []struct { tests := []struct {
name, method string name, method string
opts *bind.CallOpts opts *bind.CallOpts
@ -482,6 +485,7 @@ func TestCall(t *testing.T) {
results: &[]interface{}{0}, results: &[]interface{}{0},
wantErr: true, wantErr: true,
}} }}
for _, test := range tests { for _, test := range tests {
bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{ bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{
Methods: map[string]abi.Method{ Methods: map[string]abi.Method{
@ -496,15 +500,19 @@ func TestCall(t *testing.T) {
}, },
}, test.mc, nil, nil) }, test.mc, nil, nil)
err := bc.Call(test.opts, test.results, test.method) err := bc.Call(test.opts, test.results, test.method)
if test.wantErr || test.wantErrExact != nil { if test.wantErr || test.wantErrExact != nil {
if err == nil { if err == nil {
t.Fatalf("%q expected error", test.name) t.Fatalf("%q expected error", test.name)
} }
if test.wantErrExact != nil && !errors.Is(err, test.wantErrExact) { if test.wantErrExact != nil && !errors.Is(err, test.wantErrExact) {
t.Fatalf("%q expected error %q but got %q", test.name, test.wantErrExact, err) t.Fatalf("%q expected error %q but got %q", test.name, test.wantErrExact, err)
} }
continue continue
} }
if err != nil { if err != nil {
t.Fatalf("%q unexpected error: %v", test.name, err) t.Fatalf("%q unexpected error: %v", test.name, err)
} }

View file

@ -99,6 +99,7 @@ func abigen(c *cli.Context) error {
utils.Fatalf("No destination package specified (--pkg)") utils.Fatalf("No destination package specified (--pkg)")
} }
var lang bind.Lang var lang bind.Lang
switch c.String(langFlag.Name) { switch c.String(langFlag.Name) {
case "go": case "go":
lang = bind.LangGo lang = bind.LangGo
@ -120,6 +121,7 @@ func abigen(c *cli.Context) error {
abi []byte abi []byte
err error err error
) )
input := c.String(abiFlag.Name) input := c.String(abiFlag.Name)
if input == "-" { if input == "-" {
abi, err = io.ReadAll(os.Stdin) abi, err = io.ReadAll(os.Stdin)
@ -132,6 +134,7 @@ func abigen(c *cli.Context) error {
abis = append(abis, string(abi)) abis = append(abis, string(abi))
var bin []byte var bin []byte
if binFile := c.String(binFlag.Name); binFile != "" { if binFile := c.String(binFlag.Name); binFile != "" {
if bin, err = os.ReadFile(binFile); err != nil { if bin, err = os.ReadFile(binFile); err != nil {
utils.Fatalf("Failed to read input bytecode: %v", err) utils.Fatalf("Failed to read input bytecode: %v", err)
@ -225,6 +228,7 @@ func abigen(c *cli.Context) error {
fmt.Printf("%s\n", code) fmt.Printf("%s\n", code)
return nil return nil
} }
if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil { if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil {
utils.Fatalf("Failed to write ABI binding: %v", err) utils.Fatalf("Failed to write ABI binding: %v", err)
} }

View file

@ -22,6 +22,7 @@ func newNameFilter(patterns ...string) (*nameFilter, error) {
return nil, err return nil, err
} }
} }
return f, nil return f, nil
} }
@ -40,7 +41,9 @@ func (f *nameFilter) add(pattern string) error {
f.files[file] = true f.files[file] = true
return nil return nil
} }
f.fulls[pattern] = true f.fulls[pattern] = true
return nil return nil
} }

View file

@ -66,6 +66,7 @@ func getCheckpoint(ctx *cli.Context, client *rpc.Client) *params.TrustedCheckpoi
if ctx.IsSet(indexFlag.Name) { if ctx.IsSet(indexFlag.Name) {
var result [3]string var result [3]string
index := uint64(ctx.Int64(indexFlag.Name)) index := uint64(ctx.Int64(indexFlag.Name))
if err := client.Call(&result, "les_getCheckpoint", index); err != nil { if err := client.Call(&result, "les_getCheckpoint", index); err != nil {
utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err) utils.Fatalf("Failed to get local checkpoint %v, please ensure the les API is exposed", err)

View file

@ -329,6 +329,7 @@ func initializeSecrets(c *cli.Context) error {
return fmt.Errorf("failed to read enough random") return fmt.Errorf("failed to read enough random")
} }
n, p := keystore.StandardScryptN, keystore.StandardScryptP n, p := keystore.StandardScryptN, keystore.StandardScryptP
if c.Bool(utils.LightKDFFlag.Name) { if c.Bool(utils.LightKDFFlag.Name) {
n, p = keystore.LightScryptN, keystore.LightScryptP n, p = keystore.LightScryptN, keystore.LightScryptP
} }
@ -385,6 +386,7 @@ func attestFile(ctx *cli.Context) error {
if err != nil { if err != nil {
utils.Fatalf(err.Error()) utils.Fatalf(err.Error())
} }
configDir := ctx.String(configdirFlag.Name) configDir := ctx.String(configdirFlag.Name)
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
confKey := crypto.Keccak256([]byte("config"), stretchedKey) confKey := crypto.Keccak256([]byte("config"), stretchedKey)
@ -401,15 +403,18 @@ func initInternalApi(c *cli.Context) (*core.UIServerAPI, core.UIClientAPI, error
if err := initialize(c); err != nil { if err := initialize(c); err != nil {
return nil, nil, err return nil, nil, err
} }
var ( var (
ui = core.NewCommandlineUI() ui = core.NewCommandlineUI()
pwStorage storage.Storage = &storage.NoStorage{} pwStorage storage.Storage = &storage.NoStorage{}
ksLoc = c.String(keystoreFlag.Name) ksLoc = c.String(keystoreFlag.Name)
lightKdf = c.Bool(utils.LightKDFFlag.Name) lightKdf = c.Bool(utils.LightKDFFlag.Name)
) )
am := core.StartClefAccountManager(ksLoc, true, lightKdf, "") am := core.StartClefAccountManager(ksLoc, true, lightKdf, "")
api := core.NewSignerAPI(am, 0, true, ui, nil, false, pwStorage) api := core.NewSignerAPI(am, 0, true, ui, nil, false, pwStorage)
internalApi := core.NewUIServerAPI(api) internalApi := core.NewUIServerAPI(api)
return internalApi, ui, nil return internalApi, ui, nil
} }
@ -432,6 +437,7 @@ func setCredential(ctx *cli.Context) error {
if err != nil { if err != nil {
utils.Fatalf(err.Error()) utils.Fatalf(err.Error())
} }
configDir := ctx.String(configdirFlag.Name) configDir := ctx.String(configdirFlag.Name)
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey) pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
@ -460,6 +466,7 @@ func removeCredential(ctx *cli.Context) error {
if err != nil { if err != nil {
utils.Fatalf(err.Error()) utils.Fatalf(err.Error())
} }
configDir := ctx.String(configdirFlag.Name) configDir := ctx.String(configdirFlag.Name)
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10])) vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey) pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
@ -501,10 +508,13 @@ func newAccount(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
addr, err := internalApi.New(context.Background()) addr, err := internalApi.New(context.Background())
if err == nil { if err == nil {
fmt.Printf("Generated account %v\n", addr.String()) fmt.Printf("Generated account %v\n", addr.String())
} }
return err return err
} }
@ -513,17 +523,23 @@ func listAccounts(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
accs, err := internalApi.ListAccounts(context.Background()) accs, err := internalApi.ListAccounts(context.Background())
if err != nil { if err != nil {
return err return err
} }
if len(accs) == 0 { if len(accs) == 0 {
fmt.Println("\nThe keystore is empty.") fmt.Println("\nThe keystore is empty.")
} }
fmt.Println() fmt.Println()
for _, account := range accs { for _, account := range accs {
fmt.Printf("%v (%v)\n", account.Address, account.URL) fmt.Printf("%v (%v)\n", account.Address, account.URL)
} }
return err return err
} }
@ -532,18 +548,25 @@ func listWallets(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
wallets := internalApi.ListWallets() wallets := internalApi.ListWallets()
if len(wallets) == 0 { if len(wallets) == 0 {
fmt.Println("\nThere are no wallets.") fmt.Println("\nThere are no wallets.")
} }
fmt.Println() fmt.Println()
for i, wallet := range wallets { for i, wallet := range wallets {
fmt.Printf("- Wallet %d at %v (%v %v)\n", i, wallet.URL, wallet.Status, wallet.Failure) fmt.Printf("- Wallet %d at %v (%v %v)\n", i, wallet.URL, wallet.Status, wallet.Failure)
for j, acc := range wallet.Accounts { for j, acc := range wallet.Accounts {
fmt.Printf(" -Account %d: %v (%v)\n", j, acc.Address, acc.URL) fmt.Printf(" -Account %d: %v (%v)\n", j, acc.Address, acc.URL)
} }
fmt.Println() fmt.Println()
} }
return nil return nil
} }
@ -552,14 +575,19 @@ func accountImport(c *cli.Context) error {
if c.Args().Len() != 1 { if c.Args().Len() != 1 {
return errors.New("<keyfile> must be given as first argument.") return errors.New("<keyfile> must be given as first argument.")
} }
internalApi, ui, err := initInternalApi(c) internalApi, ui, err := initInternalApi(c)
if err != nil { if err != nil {
return err return err
} }
pKey, err := crypto.LoadECDSA(c.Args().First()) pKey, err := crypto.LoadECDSA(c.Args().First())
if err != nil { if err != nil {
return err return err
} }
readPw := func(prompt string) (string, error) { readPw := func(prompt string) (string, error) {
resp, err := ui.OnInputRequired(core.UserInputRequest{ resp, err := ui.OnInputRequired(core.UserInputRequest{
Title: "Password", Title: "Password",
@ -569,23 +597,31 @@ func accountImport(c *cli.Context) error {
if err != nil { if err != nil {
return "", err return "", err
} }
return resp.Text, nil return resp.Text, nil
} }
first, err := readPw("Please enter a password for the imported account") first, err := readPw("Please enter a password for the imported account")
if err != nil { if err != nil {
return err return err
} }
second, err := readPw("Please repeat the password you just entered") second, err := readPw("Please repeat the password you just entered")
if err != nil { if err != nil {
return err return err
} }
if first != second { if first != second {
return errors.New("Passwords do not match") return errors.New("Passwords do not match")
} }
acc, err := internalApi.ImportRawKey(hex.EncodeToString(crypto.FromECDSA(pKey)), first) acc, err := internalApi.ImportRawKey(hex.EncodeToString(crypto.FromECDSA(pKey)), first)
if err != nil { if err != nil {
return err return err
} }
ui.ShowInfo(fmt.Sprintf(`Key imported: ui.ShowInfo(fmt.Sprintf(`Key imported:
Address %v Address %v
Keystore file: %v Keystore file: %v
@ -595,6 +631,7 @@ access to the key and all associated funds!
Make sure to backup keystore and passwords in a safe location.`, Make sure to backup keystore and passwords in a safe location.`,
acc.Address, acc.URL.Path)) acc.Address, acc.URL.Path))
return nil return nil
} }
@ -630,6 +667,7 @@ func signer(c *cli.Context) error {
var ( var (
ui core.UIClientAPI ui core.UIClientAPI
) )
if c.Bool(stdiouiFlag.Name) { if c.Bool(stdiouiFlag.Name) {
log.Info("Using stdin/stdout as UI-channel") log.Info("Using stdin/stdout as UI-channel")
ui = core.NewStdIOUI() ui = core.NewStdIOUI()
@ -650,6 +688,7 @@ func signer(c *cli.Context) error {
api core.ExternalAPI api core.ExternalAPI
pwStorage storage.Storage = &storage.NoStorage{} pwStorage storage.Storage = &storage.NoStorage{}
) )
configDir := c.String(configdirFlag.Name) configDir := c.String(configdirFlag.Name)
if stretchedKey, err := readMasterKey(c, ui); err != nil { if stretchedKey, err := readMasterKey(c, ui); err != nil {
log.Warn("Failed to open master, rules disabled", "err", err) log.Warn("Failed to open master, rules disabled", "err", err)
@ -727,6 +766,7 @@ func signer(c *cli.Context) error {
Service: api, Service: api,
}, },
} }
if c.Bool(utils.HTTPEnabledFlag.Name) { if c.Bool(utils.HTTPEnabledFlag.Name) {
vhosts := utils.SplitAndTrim(c.String(utils.HTTPVirtualHostsFlag.Name)) vhosts := utils.SplitAndTrim(c.String(utils.HTTPVirtualHostsFlag.Name))
cors := utils.SplitAndTrim(c.String(utils.HTTPCORSDomainFlag.Name)) cors := utils.SplitAndTrim(c.String(utils.HTTPCORSDomainFlag.Name))
@ -756,6 +796,7 @@ func signer(c *cli.Context) error {
log.Info("HTTP endpoint closed", "url", extapiURL) log.Info("HTTP endpoint closed", "url", extapiURL)
}() }()
} }
if !c.Bool(utils.IPCDisabledFlag.Name) { if !c.Bool(utils.IPCDisabledFlag.Name) {
givenPath := c.String(utils.IPCPathFlag.Name) givenPath := c.String(utils.IPCPathFlag.Name)
ipcapiURL = ipcEndpoint(filepath.Join(givenPath, "clef.ipc"), configDir) ipcapiURL = ipcEndpoint(filepath.Join(givenPath, "clef.ipc"), configDir)
@ -769,6 +810,7 @@ func signer(c *cli.Context) error {
log.Info("IPC endpoint closed", "url", ipcapiURL) log.Info("IPC endpoint closed", "url", ipcapiURL)
}() }()
} }
if c.Bool(testFlag.Name) { if c.Bool(testFlag.Name) {
log.Info("Performing UI test") log.Info("Performing UI test")
go testExternalUI(apiImpl) go testExternalUI(apiImpl)
@ -816,6 +858,7 @@ func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
file string file string
configDir = ctx.String(configdirFlag.Name) configDir = ctx.String(configdirFlag.Name)
) )
if ctx.IsSet(signerSecretFlag.Name) { if ctx.IsSet(signerSecretFlag.Name) {
file = ctx.String(signerSecretFlag.Name) file = ctx.String(signerSecretFlag.Name)
} else { } else {
@ -824,6 +867,7 @@ func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
if err := checkFile(file); err != nil { if err := checkFile(file); err != nil {
return nil, err return nil, err
} }
cipherKey, err := os.ReadFile(file) cipherKey, err := os.ReadFile(file)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1215,5 +1259,6 @@ These data types are defined in the channel between clef and the UI`)
for _, elem := range output { for _, elem := range output {
fmt.Println(elem) fmt.Println(elem)
} }
return nil return nil
} }

View file

@ -50,6 +50,7 @@ func TestMain(m *testing.M) {
if reexec.Init() { if reexec.Init() {
return return
} }
os.Exit(m.Run()) os.Exit(m.Run())
} }
@ -63,9 +64,11 @@ func runClef(t *testing.T, args ...string) *testproc {
if err != nil { if err != nil {
return nil return nil
} }
t.Cleanup(func() { t.Cleanup(func() {
os.RemoveAll(ddir) os.RemoveAll(ddir)
}) })
return runWithKeystore(t, ddir, args...) return runWithKeystore(t, ddir, args...)
} }
@ -81,6 +84,7 @@ func runWithKeystore(t *testing.T, keystore string, args ...string) *testproc {
// Boot "clef". This actually runs the test binary but the TestMain // Boot "clef". This actually runs the test binary but the TestMain
// function will prevent any tests from running. // function will prevent any tests from running.
tt.Run(registeredName, args...) tt.Run(registeredName, args...)
return tt return tt
} }

View file

@ -78,6 +78,7 @@ func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
doneCh = make(chan enode.Iterator, len(c.iters)) doneCh = make(chan enode.Iterator, len(c.iters))
liveIters = len(c.iters) liveIters = len(c.iters)
) )
if nthreads < 1 { if nthreads < 1 {
nthreads = 1 nthreads = 1
} }
@ -86,6 +87,7 @@ func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
for _, it := range c.iters { for _, it := range c.iters {
go c.runIterator(doneCh, it) go c.runIterator(doneCh, it)
} }
var ( var (
added uint64 added uint64
updated uint64 updated uint64
@ -94,10 +96,13 @@ func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
removed uint64 removed uint64
wg sync.WaitGroup wg sync.WaitGroup
) )
wg.Add(nthreads) wg.Add(nthreads)
for i := 0; i < nthreads; i++ { for i := 0; i < nthreads; i++ {
go func() { go func() {
defer wg.Done() defer wg.Done()
for { for {
select { select {
case n := <-c.ch: case n := <-c.ch:
@ -183,6 +188,7 @@ func (c *crawler) updateNode(n *enode.Node) int {
// Request the node record. // Request the node record.
status := nodeUpdated status := nodeUpdated
node.LastCheck = truncNow() node.LastCheck = truncNow()
if nn, err := c.disc.RequestENR(n); err != nil { if nn, err := c.disc.RequestENR(n); err != nil {
if node.Score == 0 { if node.Score == 0 {
// Node doesn't implement EIP-868. // Node doesn't implement EIP-868.
@ -206,10 +212,13 @@ func (c *crawler) updateNode(n *enode.Node) int {
if node.Score <= 0 { if node.Score <= 0 {
log.Debug("Removing node", "id", n.ID()) log.Debug("Removing node", "id", n.ID())
delete(c.output, n.ID()) delete(c.output, n.ID())
return nodeRemoved return nodeRemoved
} }
log.Debug("Updating node", "id", n.ID(), "seq", n.Seq(), "score", node.Score) log.Debug("Updating node", "id", n.ID(), "seq", n.Seq(), "score", node.Score)
c.output[n.ID()] = node c.output[n.ID()] = node
return status return status
} }

View file

@ -282,18 +282,25 @@ func parseExtAddr(spec string) (ip net.IP, port int, ok bool) {
if ip != nil { if ip != nil {
return ip, 0, true return ip, 0, true
} }
host, portstr, err := net.SplitHostPort(spec) host, portstr, err := net.SplitHostPort(spec)
if err != nil { if err != nil {
return nil, 0, false return nil, 0, false
} }
ip = net.ParseIP(host) ip = net.ParseIP(host)
if ip == nil { if ip == nil {
return nil, 0, false return nil, 0, false
} }
port, err = strconv.Atoi(portstr) port, err = strconv.Atoi(portstr)
if err != nil { if err != nil {
return nil, 0, false return nil, 0, false
} }
return ip, port, true return ip, port, true
} }
@ -326,7 +333,9 @@ func listen(ctx *cli.Context, ln *enode.LocalNode) *net.UDPConn {
if !ok { if !ok {
exit(fmt.Errorf("-%s: invalid external address %q", extAddrFlag.Name, extAddr)) exit(fmt.Errorf("-%s: invalid external address %q", extAddrFlag.Name, extAddr))
} }
ln.SetStaticIP(ip) ln.SetStaticIP(ip)
if port != 0 { if port != 0 {
ln.SetFallbackUDP(port) ln.SetFallbackUDP(port)
} }

View file

@ -127,6 +127,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
// Iterate over the new records and inject anything missing. // Iterate over the new records and inject anything missing.
log.Info("Updating DNS entries") log.Info("Updating DNS entries")
created := 0 created := 0
updated := 0 updated := 0
skipped := 0 skipped := 0
@ -156,9 +157,11 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
return fmt.Errorf("failed to publish %s: %v", path, err) return fmt.Errorf("failed to publish %s: %v", path, err)
} }
} }
log.Info("Updated DNS entries", "new", created, "updated", updated, "untouched", skipped) log.Info("Updated DNS entries", "new", created, "updated", updated, "untouched", skipped)
// Iterate over the old records and delete anything stale. // Iterate over the old records and delete anything stale.
deleted := 0 deleted := 0
log.Info("Deleting stale DNS entries") log.Info("Deleting stale DNS entries")
for path, entry := range existing { for path, entry := range existing {
if _, ok := records[path]; ok { if _, ok := records[path]; ok {
@ -171,6 +174,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
return fmt.Errorf("failed to delete %s: %v", path, err) return fmt.Errorf("failed to delete %s: %v", path, err)
} }
} }
log.Info("Deleted stale DNS entries", "count", deleted) log.Info("Deleted stale DNS entries", "count", deleted)
return nil return nil
} }

View file

@ -279,6 +279,7 @@ func makeDeletionChanges(records map[string]recordSet, keep map[string]string) [
if _, ok := keep[path]; ok { if _, ok := keep[path]; ok {
continue continue
} }
log.Debug(fmt.Sprintf("Deleting %s = %s", path, strings.Join(set.values, ""))) log.Debug(fmt.Sprintf("Deleting %s = %s", path, strings.Join(set.values, "")))
changes = append(changes, newTXTChange("DELETE", path, set.ttl, set.values...)) changes = append(changes, newTXTChange("DELETE", path, set.ttl, set.values...))
} }
@ -345,6 +346,7 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error
var req route53.ListResourceRecordSetsInput var req route53.ListResourceRecordSetsInput
req.HostedZoneId = &c.zoneID req.HostedZoneId = &c.zoneID
existing := make(map[string]recordSet) existing := make(map[string]recordSet)
log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID) log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID)
for page := 0; ; page++ { for page := 0; ; page++ {
log.Debug("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page) log.Debug("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page)

View file

@ -381,6 +381,7 @@ func writeTreeMetadata(directory string, def *dnsDefinition) {
exit(err) exit(err)
} }
metaFile, _ := treeDefinitionFiles(directory) metaFile, _ := treeDefinitionFiles(directory)
if err := os.WriteFile(metaFile, metaJSON, 0644); err != nil { if err := os.WriteFile(metaFile, metaJSON, 0644); err != nil {
exit(err) exit(err)
} }
@ -410,6 +411,7 @@ func writeTXTJSON(file string, txt map[string]string) {
fmt.Println() fmt.Println()
return return
} }
if err := os.WriteFile(file, txtJSON, 0644); err != nil { if err := os.WriteFile(file, txtJSON, 0644); err != nil {
exit(err) exit(err)
} }

View file

@ -139,6 +139,7 @@ func loadChain(chainfile string, genesis string) (*Chain, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
gblock := gen.ToBlock() gblock := gen.ToBlock()
blocks, err := blocksFromFile(chainfile, gblock) blocks, err := blocksFromFile(chainfile, gblock)

View file

@ -208,14 +208,18 @@ loop:
// node, and one for receiving messages from the node. // node, and one for receiving messages from the node.
func (s *Suite) createSendAndRecvConns() (*Conn, *Conn, error) { func (s *Suite) createSendAndRecvConns() (*Conn, *Conn, error) {
sendConn, err := s.dial() sendConn, err := s.dial()
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("dial failed: %v", err) return nil, nil, fmt.Errorf("dial failed: %v", err)
} }
recvConn, err := s.dial() recvConn, err := s.dial()
if err != nil { if err != nil {
sendConn.Close() sendConn.Close()
return nil, nil, fmt.Errorf("dial failed: %v", err) return nil, nil, fmt.Errorf("dial failed: %v", err)
} }
return sendConn, recvConn, nil return sendConn, recvConn, nil
} }
@ -235,10 +239,12 @@ func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
if err != nil { if err != nil {
return errorf("could not get headers for inbound header request: %v", err) return errorf("could not get headers for inbound header request: %v", err)
} }
resp := &BlockHeaders{ resp := &BlockHeaders{
RequestId: msg.ReqID(), RequestId: msg.ReqID(),
BlockHeadersPacket: eth.BlockHeadersPacket(headers), BlockHeadersPacket: eth.BlockHeadersPacket(headers),
} }
if err := c.Write(resp); err != nil { if err := c.Write(resp); err != nil {
return errorf("could not write to connection: %v", err) return errorf("could not write to connection: %v", err)
} }
@ -246,6 +252,7 @@ func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
return msg return msg
} }
} }
return errorf("no message received within %v", timeout) return errorf("no message received within %v", timeout)
} }
@ -263,10 +270,13 @@ func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, reqID uint
// wait for response // wait for response
msg := c.waitForResponse(chain, timeout, request.RequestId) msg := c.waitForResponse(chain, timeout, request.RequestId)
resp, ok := msg.(*BlockHeaders) resp, ok := msg.(*BlockHeaders)
if !ok { if !ok {
return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg)) return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
} }
headers := []*types.Header(resp.BlockHeadersPacket) headers := []*types.Header(resp.BlockHeadersPacket)
return headers, nil return headers, nil
} }
@ -591,21 +601,26 @@ func (s *Suite) hashAnnounce() error {
// Announcement sent, now wait for a header request // Announcement sent, now wait for a header request
msg := sendConn.Read() msg := sendConn.Read()
blockHeaderReq, ok := msg.(*GetBlockHeaders) blockHeaderReq, ok := msg.(*GetBlockHeaders)
if !ok { if !ok {
return fmt.Errorf("unexpected %s", pretty.Sdump(msg)) return fmt.Errorf("unexpected %s", pretty.Sdump(msg))
} }
if blockHeaderReq.Amount != 1 { if blockHeaderReq.Amount != 1 {
return fmt.Errorf("unexpected number of block headers requested: %v", blockHeaderReq.Amount) return fmt.Errorf("unexpected number of block headers requested: %v", blockHeaderReq.Amount)
} }
if blockHeaderReq.Origin.Hash != announcement.Hash { if blockHeaderReq.Origin.Hash != announcement.Hash {
return fmt.Errorf("unexpected block header requested. Announced:\n %v\n Remote request:\n%v", return fmt.Errorf("unexpected block header requested. Announced:\n %v\n Remote request:\n%v",
pretty.Sdump(announcement), pretty.Sdump(announcement),
pretty.Sdump(blockHeaderReq)) pretty.Sdump(blockHeaderReq))
} }
err = sendConn.Write(&BlockHeaders{ err = sendConn.Write(&BlockHeaders{
RequestId: blockHeaderReq.ReqID(), RequestId: blockHeaderReq.ReqID(),
BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()}, BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()},
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to write to connection: %v", err) return fmt.Errorf("failed to write to connection: %v", err)
} }

View file

@ -357,6 +357,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
for i := 1; i <= 65; i++ { for i := 1; i <= 65; i++ {
accPaths = append(accPaths, pathTo(i)) accPaths = append(accPaths, pathTo(i))
} }
empty := types.EmptyCodeHash empty := types.EmptyCodeHash
for i, tc := range []trieNodesTest{ for i, tc := range []trieNodesTest{
{ {

View file

@ -197,13 +197,16 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
if err != nil { if err != nil {
t.Fatalf("failed to get expected headers for request 1: %v", err) t.Fatalf("failed to get expected headers for request 1: %v", err)
} }
expected2, err := s.chain.GetHeaders(req2) expected2, err := s.chain.GetHeaders(req2)
if err != nil { if err != nil {
t.Fatalf("failed to get expected headers for request 2: %v", err) t.Fatalf("failed to get expected headers for request 2: %v", err)
} }
if !headersMatch(expected1, headers1.BlockHeadersPacket) { if !headersMatch(expected1, headers1.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
} }
if !headersMatch(expected2, headers2.BlockHeadersPacket) { if !headersMatch(expected2, headers2.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
} }
@ -245,6 +248,7 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
if err = conn.Write(request1); err != nil { if err = conn.Write(request1); err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }
if err = conn.Write(request2); err != nil { if err = conn.Write(request2); err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }
@ -266,13 +270,16 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
if err != nil { if err != nil {
t.Fatalf("failed to get expected block headers: %v", err) t.Fatalf("failed to get expected block headers: %v", err)
} }
expected2, err := s.chain.GetHeaders(request2) expected2, err := s.chain.GetHeaders(request2)
if err != nil { if err != nil {
t.Fatalf("failed to get expected block headers: %v", err) t.Fatalf("failed to get expected block headers: %v", err)
} }
if !headersMatch(expected1, headers1.BlockHeadersPacket) { if !headersMatch(expected1, headers1.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
} }
if !headersMatch(expected2, headers2.BlockHeadersPacket) { if !headersMatch(expected2, headers2.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
} }
@ -299,6 +306,7 @@ func (s *Suite) TestZeroRequestID(t *utesting.T) {
if err != nil { if err != nil {
t.Fatalf("failed to get block headers: %v", err) t.Fatalf("failed to get block headers: %v", err)
} }
expected, err := s.chain.GetHeaders(req) expected, err := s.chain.GetHeaders(req)
if err != nil { if err != nil {
t.Fatalf("failed to get expected block headers: %v", err) t.Fatalf("failed to get expected block headers: %v", err)
@ -336,8 +344,10 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
if !ok { if !ok {
t.Fatalf("unexpected: %s", pretty.Sdump(msg)) t.Fatalf("unexpected: %s", pretty.Sdump(msg))
} }
bodies := resp.BlockBodiesPacket bodies := resp.BlockBodiesPacket
t.Logf("received %d block bodies", len(bodies)) t.Logf("received %d block bodies", len(bodies))
if len(bodies) != len(req.GetBlockBodiesPacket) { if len(bodies) != len(req.GetBlockBodiesPacket) {
t.Fatalf("wrong bodies in response: expected %d bodies, "+ t.Fatalf("wrong bodies in response: expected %d bodies, "+
"got %d", len(req.GetBlockBodiesPacket), len(bodies)) "got %d", len(req.GetBlockBodiesPacket), len(bodies))
@ -372,6 +382,7 @@ func (s *Suite) TestLargeAnnounce(t *utesting.T) {
for i, blockAnnouncement := range blocks[0:3] { for i, blockAnnouncement := range blocks[0:3] {
t.Logf("Testing malicious announcement: %v\n", i) t.Logf("Testing malicious announcement: %v\n", i)
conn, err := s.dial() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
@ -480,10 +491,12 @@ func (s *Suite) TestLargeTxRequest(t *utesting.T) {
for _, hash := range hashMap { for _, hash := range hashMap {
hashes = append(hashes, hash) hashes = append(hashes, hash)
} }
getTxReq := &GetPooledTransactions{ getTxReq := &GetPooledTransactions{
RequestId: 1234, RequestId: 1234,
GetPooledTransactionsPacket: hashes, GetPooledTransactionsPacket: hashes,
} }
if err = conn.Write(getTxReq); err != nil { if err = conn.Write(getTxReq); err != nil {
t.Fatalf("could not write to conn: %v", err) t.Fatalf("could not write to conn: %v", err)
} }
@ -514,9 +527,11 @@ func (s *Suite) TestNewPooledTxs(t *utesting.T) {
if err != nil { if err != nil {
t.Fatalf("failed to generate transactions: %v", err) t.Fatalf("failed to generate transactions: %v", err)
} }
hashes := make([]common.Hash, len(txs)) hashes := make([]common.Hash, len(txs))
types := make([]byte, len(txs)) types := make([]byte, len(txs))
sizes := make([]uint32, len(txs)) sizes := make([]uint32, len(txs))
for i, tx := range txs { for i, tx := range txs {
hashes[i] = tx.Hash() hashes[i] = tx.Hash()
types[i] = tx.Type() types[i] = tx.Type()
@ -534,10 +549,13 @@ func (s *Suite) TestNewPooledTxs(t *utesting.T) {
} }
var ann Message = NewPooledTransactionHashes{Types: types, Sizes: sizes, Hashes: hashes} var ann Message = NewPooledTransactionHashes{Types: types, Sizes: sizes, Hashes: hashes}
if conn.negotiatedProtoVersion < eth.ETH68 { if conn.negotiatedProtoVersion < eth.ETH68 {
ann = NewPooledTransactionHashes66(hashes) ann = NewPooledTransactionHashes66(hashes)
} }
err = conn.Write(ann) err = conn.Write(ann)
if err != nil { if err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }

View file

@ -45,8 +45,11 @@ func TestEthSuite(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("could not create new test suite: %v", err) t.Fatalf("could not create new test suite: %v", err)
} }
for _, test := range suite.EthTests() { for _, test := range suite.EthTests() {
test := test
t.Run(test.Name, func(t *testing.T) { t.Run(test.Name, func(t *testing.T) {
t.Parallel()
result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout) result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed { if result[0].Failed {
t.Fatal() t.Fatal()

View file

@ -115,6 +115,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
if len(txHashes) != len(msg.Sizes) { if len(txHashes) != len(msg.Sizes) {
return fmt.Errorf("invalid msg size lengths: hashes: %v sizes: %v", len(txHashes), len(msg.Sizes)) return fmt.Errorf("invalid msg size lengths: hashes: %v sizes: %v", len(txHashes), len(msg.Sizes))
} }
if len(txHashes) != len(msg.Types) { if len(txHashes) != len(msg.Types) {
return fmt.Errorf("invalid msg type lengths: hashes: %v types: %v", len(txHashes), len(msg.Types)) return fmt.Errorf("invalid msg type lengths: hashes: %v types: %v", len(txHashes), len(msg.Types))
} }
@ -124,11 +125,13 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
continue continue
} }
} }
for index, gotHash := range txHashes { for index, gotHash := range txHashes {
if gotHash == tx.Hash() { if gotHash == tx.Hash() {
if msg.Sizes[index] != uint32(tx.Size()) { if msg.Sizes[index] != uint32(tx.Size()) {
return fmt.Errorf("invalid tx size: got %v want %v", msg.Sizes[index], tx.Size()) return fmt.Errorf("invalid tx size: got %v want %v", msg.Sizes[index], tx.Size())
} }
if msg.Types[index] != tx.Type() { if msg.Types[index] != tx.Type() {
return fmt.Errorf("invalid tx type: got %v want %v", msg.Types[index], tx.Type()) return fmt.Errorf("invalid tx type: got %v want %v", msg.Types[index], tx.Type())
} }
@ -136,6 +139,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
return nil return nil
} }
} }
return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash()) return fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash())
default: default:
@ -165,6 +169,7 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T) error {
for i, tx := range badTxs { for i, tx := range badTxs {
t.Logf("Testing malicious tx propagation: %v\n", i) t.Logf("Testing malicious tx propagation: %v\n", i)
if err = sendMaliciousTx(s, tx); err != nil { if err = sendMaliciousTx(s, tx); err != nil {
return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err) return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err)
} }

View file

@ -183,24 +183,28 @@ func (c *Conn) Read() Message {
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return (*GetBlockHeaders)(ethMsg) return (*GetBlockHeaders)(ethMsg)
case (BlockHeaders{}).Code(): case (BlockHeaders{}).Code():
ethMsg := new(eth.BlockHeadersPacket66) ethMsg := new(eth.BlockHeadersPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return (*BlockHeaders)(ethMsg) return (*BlockHeaders)(ethMsg)
case (GetBlockBodies{}).Code(): case (GetBlockBodies{}).Code():
ethMsg := new(eth.GetBlockBodiesPacket66) ethMsg := new(eth.GetBlockBodiesPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return (*GetBlockBodies)(ethMsg) return (*GetBlockBodies)(ethMsg)
case (BlockBodies{}).Code(): case (BlockBodies{}).Code():
ethMsg := new(eth.BlockBodiesPacket66) ethMsg := new(eth.BlockBodiesPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return (*BlockBodies)(ethMsg) return (*BlockBodies)(ethMsg)
case (NewBlock{}).Code(): case (NewBlock{}).Code():
msg = new(NewBlock) msg = new(NewBlock)
@ -214,18 +218,21 @@ func (c *Conn) Read() Message {
if err := rlp.DecodeBytes(rawData, ethMsg); err == nil { if err := rlp.DecodeBytes(rawData, ethMsg); err == nil {
return ethMsg return ethMsg
} }
msg = new(NewPooledTransactionHashes66) msg = new(NewPooledTransactionHashes66)
case (GetPooledTransactions{}.Code()): case (GetPooledTransactions{}.Code()):
ethMsg := new(eth.GetPooledTransactionsPacket66) ethMsg := new(eth.GetPooledTransactionsPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return (*GetPooledTransactions)(ethMsg) return (*GetPooledTransactions)(ethMsg)
case (PooledTransactions{}.Code()): case (PooledTransactions{}.Code()):
ethMsg := new(eth.PooledTransactionsPacket66) ethMsg := new(eth.PooledTransactionsPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return (*PooledTransactions)(ethMsg) return (*PooledTransactions)(ethMsg)
default: default:
msg = errorf("invalid message code: %d", code) msg = errorf("invalid message code: %d", code)
@ -235,8 +242,10 @@ func (c *Conn) Read() Message {
if err := rlp.DecodeBytes(rawData, msg); err != nil { if err := rlp.DecodeBytes(rawData, msg); err != nil {
return errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return msg return msg
} }
return errorf("invalid message: %s", string(rawData)) return errorf("invalid message: %s", string(rawData))
} }

View file

@ -102,7 +102,9 @@ func keyToID(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
fmt.Println(n.ID()) fmt.Println(n.ID())
return nil return nil
} }
@ -111,7 +113,9 @@ func keyToURL(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
fmt.Println(n.URLv4()) fmt.Println(n.URLv4())
return nil return nil
} }
@ -120,7 +124,9 @@ func keyToRecord(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
fmt.Println(n.String()) fmt.Println(n.String())
return nil return nil
} }
@ -141,16 +147,20 @@ func makeRecord(ctx *cli.Context) (*enode.Node, error) {
} }
var r enr.Record var r enr.Record
if host != "" { if host != "" {
ip := net.ParseIP(host) ip := net.ParseIP(host)
if ip == nil { if ip == nil {
return nil, fmt.Errorf("invalid IP address %q", host) return nil, fmt.Errorf("invalid IP address %q", host)
} }
r.Set(enr.IP(ip)) r.Set(enr.IP(ip))
} }
if udp != 0 { if udp != 0 {
r.Set(enr.UDP(udp)) r.Set(enr.UDP(udp))
} }
if tcp != 0 { if tcp != 0 {
r.Set(enr.TCP(tcp)) r.Set(enr.TCP(tcp))
} }
@ -158,5 +168,6 @@ func makeRecord(ctx *cli.Context) (*enode.Node, error) {
if err := enode.SignV4(&r, key); err != nil { if err := enode.SignV4(&r, key); err != nil {
return nil, err return nil, err
} }
return enode.New(enode.ValidSchemes, &r) return enode.New(enode.ValidSchemes, &r)
} }

View file

@ -63,14 +63,17 @@ func main() {
func commandHasFlag(ctx *cli.Context, flag cli.Flag) bool { func commandHasFlag(ctx *cli.Context, flag cli.Flag) bool {
names := flag.Names() names := flag.Names()
set := make(map[string]struct{}, len(names)) set := make(map[string]struct{}, len(names))
for _, name := range names { for _, name := range names {
set[name] = struct{}{} set[name] = struct{}{}
} }
for _, fn := range ctx.FlagNames() { for _, fn := range ctx.FlagNames() {
if _, ok := set[fn]; ok { if _, ok := set[fn]; ok {
return true return true
} }
} }
return false return false
} }
@ -79,6 +82,7 @@ func getNodeArg(ctx *cli.Context) *enode.Node {
if ctx.NArg() < 1 { if ctx.NArg() < 1 {
exit("missing node as command-line argument") exit("missing node as command-line argument")
} }
n, err := parseNode(ctx.Args().First()) n, err := parseNode(ctx.Args().First())
if err != nil { if err != nil {
exit(err) exit(err)

View file

@ -65,6 +65,7 @@ func writeNodesJSON(file string, nodes nodeSet) {
os.Stdout.Write(nodesJSON) os.Stdout.Write(nodesJSON)
return return
} }
if err := os.WriteFile(file, nodesJSON, 0644); err != nil { if err := os.WriteFile(file, nodesJSON, 0644); err != nil {
exit(err) exit(err)
} }

View file

@ -105,10 +105,12 @@ func rlpxEthTest(ctx *cli.Context) error {
if ctx.NArg() < 3 { if ctx.NArg() < 3 {
exit("missing path to chain.rlp as command-line argument") exit("missing path to chain.rlp as command-line argument")
} }
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2)) suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
if err != nil { if err != nil {
exit(err) exit(err)
} }
return runTests(ctx, suite.EthTests()) return runTests(ctx, suite.EthTests())
} }
@ -117,6 +119,7 @@ func rlpxSnapTest(ctx *cli.Context) error {
if ctx.NArg() < 3 { if ctx.NArg() < 3 {
exit("missing path to chain.rlp as command-line argument") exit("missing path to chain.rlp as command-line argument")
} }
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2)) suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
if err != nil { if err != nil {
exit(err) exit(err)

View file

@ -147,6 +147,7 @@ func getMessage(ctx *cli.Context, msgarg int) []byte {
if ctx.NArg() > msgarg { if ctx.NArg() > msgarg {
utils.Fatalf("Can't use --msgfile and message argument at the same time.") utils.Fatalf("Can't use --msgfile and message argument at the same time.")
} }
msg, err := os.ReadFile(file) msg, err := os.ReadFile(file)
if err != nil { if err != nil {
utils.Fatalf("Can't read message file: %v", err) utils.Fatalf("Can't read message file: %v", err)
@ -155,6 +156,7 @@ func getMessage(ctx *cli.Context, msgarg int) []byte {
} else if ctx.NArg() == msgarg+1 { } else if ctx.NArg() == msgarg+1 {
return []byte(ctx.Args().Get(msgarg)) return []byte(ctx.Args().Get(msgarg))
} }
utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg()) utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg())
return nil return nil
} }

View file

@ -48,14 +48,18 @@ func blockTestCmd(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
var tests map[string]tests.BlockTest var tests map[string]tests.BlockTest
if err = json.Unmarshal(src, &tests); err != nil { if err = json.Unmarshal(src, &tests); err != nil {
return err return err
} }
for i, test := range tests { for i, test := range tests {
if err := test.Run(false); err != nil { if err := test.Run(false); err != nil {
return fmt.Errorf("test %v: %w", i, err) return fmt.Errorf("test %v: %w", i, err)
} }
} }
return nil return nil
} }

View file

@ -157,6 +157,7 @@ func (i *bbInput) ToBlock() *types.Block {
if header.Difficulty != nil { if header.Difficulty != nil {
header.Difficulty = i.Header.Difficulty header.Difficulty = i.Header.Difficulty
} }
return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers).WithWithdrawals(i.Withdrawals) return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers).WithWithdrawals(i.Withdrawals)
} }
@ -317,11 +318,13 @@ func readInput(ctx *cli.Context) (*bbInput, error) {
} }
inputData.OmmersRlp = ommers inputData.OmmersRlp = ommers
} }
if withdrawalsStr != stdinSelector && withdrawalsStr != "" { if withdrawalsStr != stdinSelector && withdrawalsStr != "" {
var withdrawals []*types.Withdrawal var withdrawals []*types.Withdrawal
if err := readFile(withdrawalsStr, "withdrawals", &withdrawals); err != nil { if err := readFile(withdrawalsStr, "withdrawals", &withdrawals); err != nil {
return nil, err return nil, err
} }
inputData.Withdrawals = withdrawals inputData.Withdrawals = withdrawals
} }
if txsStr != stdinSelector { if txsStr != stdinSelector {
@ -367,6 +370,7 @@ func dispatchBlock(ctx *cli.Context, baseDir string, block *types.Block) error {
Rlp hexutil.Bytes `json:"rlp"` Rlp hexutil.Bytes `json:"rlp"`
Hash common.Hash `json:"hash"` Hash common.Hash `json:"hash"`
} }
enc := blockInfo{ enc := blockInfo{
Rlp: raw, Rlp: raw,
Hash: block.Hash(), Hash: block.Hash(),

View file

@ -175,6 +175,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
return nil, nil, err return nil, nil, err
} }
vmConfig.Tracer = tracer vmConfig.Tracer = tracer
statedb.SetTxContext(tx.Hash(), txIndex) statedb.SetTxContext(tx.Hash(), txIndex)
var ( var (
@ -190,6 +191,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
statedb.RevertToSnapshot(snapshot) statedb.RevertToSnapshot(snapshot)
log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err) log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err)
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()}) rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
gaspool.SetGas(prevGas) gaspool.SetGas(prevGas)
continue continue
} }
@ -285,6 +287,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
GasUsed: (math.HexOrDecimal64)(gasUsed), GasUsed: (math.HexOrDecimal64)(gasUsed),
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee), BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
} }
if pre.Env.Withdrawals != nil { if pre.Env.Withdrawals != nil {
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil)) h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
execRs.WithdrawalsRoot = &h execRs.WithdrawalsRoot = &h

View file

@ -265,8 +265,10 @@ func Transition(ctx *cli.Context) error {
if chainConfig.IsShanghai(prestate.Env.Number) && prestate.Env.Withdrawals == nil { if chainConfig.IsShanghai(prestate.Env.Number) && prestate.Env.Withdrawals == nil {
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section")) return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
} }
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0 isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
env := prestate.Env env := prestate.Env
if isMerged { if isMerged {
// post-merge: // post-merge:
// - random must be supplied // - random must be supplied
@ -277,6 +279,7 @@ func Transition(ctx *cli.Context) error {
case env.Difficulty != nil && env.Difficulty.BitLen() != 0: case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env")) return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
} }
prestate.Env.Difficulty = nil prestate.Env.Difficulty = nil
} else if env.Difficulty == nil { } else if env.Difficulty == nil {
// pre-merge: // pre-merge:

View file

@ -128,6 +128,7 @@ func runCmd(ctx *cli.Context) error {
genesisConfig *core.Genesis genesisConfig *core.Genesis
preimages = ctx.Bool(DumpFlag.Name) preimages = ctx.Bool(DumpFlag.Name)
) )
if ctx.Bool(MachineFlag.Name) { if ctx.Bool(MachineFlag.Name) {
tracer = logger.NewJSONLogger(logconfig, os.Stdout) tracer = logger.NewJSONLogger(logconfig, os.Stdout)
} else if ctx.Bool(DebugFlag.Name) { } else if ctx.Bool(DebugFlag.Name) {
@ -136,6 +137,7 @@ func runCmd(ctx *cli.Context) error {
} else { } else {
debugLogger = logger.NewStructLogger(logconfig) debugLogger = logger.NewStructLogger(logconfig)
} }
if ctx.String(GenesisFlag.Name) != "" { if ctx.String(GenesisFlag.Name) != "" {
gen := readGenesis(ctx.String(GenesisFlag.Name)) gen := readGenesis(ctx.String(GenesisFlag.Name))
genesisConfig = gen genesisConfig = gen
@ -149,6 +151,7 @@ func runCmd(ctx *cli.Context) error {
statedb, _ = state.New(common.Hash{}, sdb, nil) statedb, _ = state.New(common.Hash{}, sdb, nil)
genesisConfig = new(core.Genesis) genesisConfig = new(core.Genesis)
} }
if ctx.String(SenderFlag.Name) != "" { if ctx.String(SenderFlag.Name) != "" {
sender = common.HexToAddress(ctx.String(SenderFlag.Name)) sender = common.HexToAddress(ctx.String(SenderFlag.Name))
} }
@ -159,6 +162,7 @@ func runCmd(ctx *cli.Context) error {
} }
var code []byte var code []byte
codeFileFlag := ctx.String(CodeFileFlag.Name) codeFileFlag := ctx.String(CodeFileFlag.Name)
codeFlag := ctx.String(CodeFlag.Name) codeFlag := ctx.String(CodeFlag.Name)
@ -202,6 +206,7 @@ func runCmd(ctx *cli.Context) error {
} }
code = common.Hex2Bytes(bin) code = common.Hex2Bytes(bin)
} }
initialGas := ctx.Uint64(GasFlag.Name) initialGas := ctx.Uint64(GasFlag.Name)
if genesisConfig.GasLimit != 0 { if genesisConfig.GasLimit != 0 {
initialGas = genesisConfig.GasLimit initialGas = genesisConfig.GasLimit
@ -241,6 +246,7 @@ func runCmd(ctx *cli.Context) error {
} }
var hexInput []byte var hexInput []byte
if inputFileFlag := ctx.String(InputFileFlag.Name); inputFileFlag != "" { if inputFileFlag := ctx.String(InputFileFlag.Name); inputFileFlag != "" {
var err error var err error
if hexInput, err = os.ReadFile(inputFileFlag); err != nil { if hexInput, err = os.ReadFile(inputFileFlag); err != nil {
@ -250,14 +256,18 @@ func runCmd(ctx *cli.Context) error {
} else { } else {
hexInput = []byte(ctx.String(InputFlag.Name)) hexInput = []byte(ctx.String(InputFlag.Name))
} }
hexInput = bytes.TrimSpace(hexInput) hexInput = bytes.TrimSpace(hexInput)
if len(hexInput)%2 != 0 { if len(hexInput)%2 != 0 {
fmt.Println("input length must be even") fmt.Println("input length must be even")
os.Exit(1) os.Exit(1)
} }
input := common.FromHex(string(hexInput)) input := common.FromHex(string(hexInput))
var execFunc func() ([]byte, uint64, error) var execFunc func() ([]byte, uint64, error)
if ctx.Bool(CreateFlag.Name) { if ctx.Bool(CreateFlag.Name) {
input = append(code, input...) input = append(code, input...)
execFunc = func() ([]byte, uint64, error) { execFunc = func() ([]byte, uint64, error) {

View file

@ -103,6 +103,7 @@ func stateTestCmd(ctx *cli.Context) error {
if s != nil { if s != nil {
root := s.IntermediateRoot(false) root := s.IntermediateRoot(false)
result.Root = &root result.Root = &root
if ctx.Bool(MachineFlag.Name) { if ctx.Bool(MachineFlag.Name) {
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root) fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
} }
@ -110,6 +111,7 @@ func stateTestCmd(ctx *cli.Context) error {
if err != nil { if err != nil {
// Test failed, mark as so and dump any state to aid debugging // Test failed, mark as so and dump any state to aid debugging
result.Pass, result.Error = false, err.Error() result.Pass, result.Error = false, err.Error()
if ctx.Bool(DumpFlag.Name) && s != nil { if ctx.Bool(DumpFlag.Name) && s != nil {
dump := s.RawDump(nil) dump := s.RawDump(nil)
result.State = &dump result.State = &dump

View file

@ -420,6 +420,7 @@ func (args *b11rInput) get(base string) []string {
out = append(out, "--input.ommers") out = append(out, "--input.ommers")
out = append(out, fmt.Sprintf("%v/%v", base, opt)) out = append(out, fmt.Sprintf("%v/%v", base, opt))
} }
if opt := args.inWithdrawals; opt != "" { if opt := args.inWithdrawals; opt != "" {
out = append(out, "--input.withdrawals") out = append(out, "--input.withdrawals")
out = append(out, fmt.Sprintf("%v/%v", base, opt)) out = append(out, fmt.Sprintf("%v/%v", base, opt))

View file

@ -168,6 +168,7 @@ func main() {
pass := strings.TrimSuffix(string(blob), "\n") pass := strings.TrimSuffix(string(blob), "\n")
ks := keystore.NewKeyStore(filepath.Join(os.Getenv("HOME"), ".faucet", "keys"), keystore.StandardScryptN, keystore.StandardScryptP) ks := keystore.NewKeyStore(filepath.Join(os.Getenv("HOME"), ".faucet", "keys"), keystore.StandardScryptN, keystore.StandardScryptP)
if blob, err = os.ReadFile(*accJSONFlag); err != nil { if blob, err = os.ReadFile(*accJSONFlag); err != nil {
log.Crit("Failed to read account key contents", "file", *accJSONFlag, "err", err) log.Crit("Failed to read account key contents", "file", *accJSONFlag, "err", err)
} }

View file

@ -236,6 +236,7 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr
} }
fmt.Println("Testing your password against all of them...") fmt.Println("Testing your password against all of them...")
var match *accounts.Account var match *accounts.Account
for i, a := range err.Matches { for i, a := range err.Matches {
if e := ks.Unlock(a, auth); e == nil { if e := ks.Unlock(a, auth); e == nil {
match = &err.Matches[i] match = &err.Matches[i]
@ -302,9 +303,11 @@ func accountUpdate(ctx *cli.Context) error {
} }
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
backends := stack.AccountManager().Backends(keystore.KeyStoreType) backends := stack.AccountManager().Backends(keystore.KeyStoreType)
if len(backends) == 0 { if len(backends) == 0 {
utils.Fatalf("Keystore is not available") utils.Fatalf("Keystore is not available")
} }
ks := backends[0].(*keystore.KeyStore) ks := backends[0].(*keystore.KeyStore)
for _, addr := range ctx.Args().Slice() { for _, addr := range ctx.Args().Slice() {
@ -321,6 +324,7 @@ func importWallet(ctx *cli.Context) error {
if ctx.Args().Len() != 1 { if ctx.Args().Len() != 1 {
utils.Fatalf("keyfile must be given as the only argument") utils.Fatalf("keyfile must be given as the only argument")
} }
keyfile := ctx.Args().First() keyfile := ctx.Args().First()
keyJSON, err := os.ReadFile(keyfile) keyJSON, err := os.ReadFile(keyfile)
if err != nil { if err != nil {
@ -334,6 +338,7 @@ func importWallet(ctx *cli.Context) error {
if len(backends) == 0 { if len(backends) == 0 {
utils.Fatalf("Keystore is not available") utils.Fatalf("Keystore is not available")
} }
ks := backends[0].(*keystore.KeyStore) ks := backends[0].(*keystore.KeyStore)
acct, err := ks.ImportPreSaleKey(keyJSON, passphrase) acct, err := ks.ImportPreSaleKey(keyJSON, passphrase)
if err != nil { if err != nil {
@ -347,6 +352,7 @@ func accountImport(ctx *cli.Context) error {
if ctx.Args().Len() != 1 { if ctx.Args().Len() != 1 {
utils.Fatalf("keyfile must be given as the only argument") utils.Fatalf("keyfile must be given as the only argument")
} }
keyfile := ctx.Args().First() keyfile := ctx.Args().First()
key, err := crypto.LoadECDSA(keyfile) key, err := crypto.LoadECDSA(keyfile)
if err != nil { if err != nil {
@ -359,6 +365,7 @@ func accountImport(ctx *cli.Context) error {
if len(backends) == 0 { if len(backends) == 0 {
utils.Fatalf("Keystore is not available") utils.Fatalf("Keystore is not available")
} }
ks := backends[0].(*keystore.KeyStore) ks := backends[0].(*keystore.KeyStore)
acct, err := ks.ImportECDSA(key, passphrase) acct, err := ks.ImportECDSA(key, passphrase)
if err != nil { if err != nil {

View file

@ -49,6 +49,7 @@ func TestAccountListEmpty(t *testing.T) {
func TestAccountList(t *testing.T) { func TestAccountList(t *testing.T) {
datadir := tmpDatadirWithKeystore(t) datadir := tmpDatadirWithKeystore(t)
var want = ` var want = `
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8 Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa
@ -122,12 +123,14 @@ func TestAccountHelp(t *testing.T) {
geth := runGeth(t, "account", "-h") geth := runGeth(t, "account", "-h")
geth.WaitExit() geth.WaitExit()
if have, want := geth.ExitStatus(), 0; have != want { if have, want := geth.ExitStatus(), 0; have != want {
t.Errorf("exit error, have %d want %d", have, want) t.Errorf("exit error, have %d want %d", have, want)
} }
geth = runGeth(t, "account", "import", "-h") geth = runGeth(t, "account", "import", "-h")
geth.WaitExit() geth.WaitExit()
if have, want := geth.ExitStatus(), 0; have != want { if have, want := geth.ExitStatus(), 0; have != want {
t.Errorf("exit error, have %d want %d", have, want) t.Errorf("exit error, have %d want %d", have, want)
} }
@ -136,13 +139,16 @@ func TestAccountHelp(t *testing.T) {
func importAccountWithExpect(t *testing.T, key string, expected string) { func importAccountWithExpect(t *testing.T, key string, expected string) {
dir := t.TempDir() dir := t.TempDir()
keyfile := filepath.Join(dir, "key.prv") keyfile := filepath.Join(dir, "key.prv")
if err := os.WriteFile(keyfile, []byte(key), 0600); err != nil { if err := os.WriteFile(keyfile, []byte(key), 0600); err != nil {
t.Error(err) t.Error(err)
} }
passwordFile := filepath.Join(dir, "password.txt") passwordFile := filepath.Join(dir, "password.txt")
if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil { if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
t.Error(err) t.Error(err)
} }
geth := runGeth(t, "--lightkdf", "account", "import", "-password", passwordFile, keyfile) geth := runGeth(t, "--lightkdf", "account", "import", "-password", passwordFile, keyfile)
defer geth.ExpectExit() defer geth.ExpectExit()
geth.Expect(expected) geth.Expect(expected)

View file

@ -36,26 +36,31 @@ func (t *testHandler) ServeHTTP(out http.ResponseWriter, in *http.Request) {
// that custom headers are forwarded to the target. // that custom headers are forwarded to the target.
func TestAttachWithHeaders(t *testing.T) { func TestAttachWithHeaders(t *testing.T) {
t.Parallel() t.Parallel()
ln, err := net.Listen("tcp", "localhost:0") ln, err := net.Listen("tcp", "localhost:0")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
port := ln.Addr().(*net.TCPAddr).Port
testReceiveHeaders(t, ln, "attach", "-H", "first: one", "-H", "second: two", fmt.Sprintf("http://localhost:%d", port))
// This way to do it fails due to flag ordering: // This way to do it fails due to flag ordering:
//
// testReceiveHeaders(t, ln, "-H", "first: one", "-H", "second: two", "attach", fmt.Sprintf("http://localhost:%d", port)) // testReceiveHeaders(t, ln, "-H", "first: one", "-H", "second: two", "attach", fmt.Sprintf("http://localhost:%d", port))
// This is fixed in a follow-up PR. // This is fixed in a follow-up PR.
port := ln.Addr().(*net.TCPAddr).Port
testReceiveHeaders(t, ln, "attach", "-H", "first: one", "-H", "second: two", fmt.Sprintf("http://localhost:%d", port))
} }
// TestAttachWithHeaders tests that 'geth db --remotedb' with custom headers works, i.e // TestAttachWithHeaders tests that 'geth db --remotedb' with custom headers works, i.e
// that custom headers are forwarded to the target. // that custom headers are forwarded to the target.
func TestRemoteDbWithHeaders(t *testing.T) { func TestRemoteDbWithHeaders(t *testing.T) {
t.Parallel() t.Parallel()
ln, err := net.Listen("tcp", "localhost:0") ln, err := net.Listen("tcp", "localhost:0")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
port := ln.Addr().(*net.TCPAddr).Port port := ln.Addr().(*net.TCPAddr).Port
testReceiveHeaders(t, ln, "db", "metadata", "--remotedb", fmt.Sprintf("http://localhost:%d", port), "-H", "first: one", "-H", "second: two") testReceiveHeaders(t, ln, "db", "metadata", "--remotedb", fmt.Sprintf("http://localhost:%d", port), "-H", "first: one", "-H", "second: two")
} }
@ -64,6 +69,7 @@ func testReceiveHeaders(t *testing.T, ln net.Listener, gethArgs ...string) {
t.Helper() t.Helper()
var ok uint32 var ok uint32
server := &http.Server{ server := &http.Server{
Addr: "localhost:0", Addr: "localhost:0",
Handler: &testHandler{func(w http.ResponseWriter, r *http.Request) { Handler: &testHandler{func(w http.ResponseWriter, r *http.Request) {
@ -77,8 +83,10 @@ func testReceiveHeaders(t *testing.T, ln net.Listener, gethArgs ...string) {
atomic.StoreUint32(&ok, 1) atomic.StoreUint32(&ok, 1)
}}} }}}
go server.Serve(ln) go server.Serve(ln)
defer server.Close() defer server.Close()
runGeth(t, gethArgs...).WaitExit() runGeth(t, gethArgs...).WaitExit()
if atomic.LoadUint32(&ok) != 1 { if atomic.LoadUint32(&ok) != 1 {
t.Fatal("Test fail, expected invocation to succeed") t.Fatal("Test fail, expected invocation to succeed")
} }

View file

@ -195,6 +195,7 @@ func initGenesis(ctx *cli.Context) error {
if err != nil { if err != nil {
utils.Fatalf("Failed to open database: %v", err) utils.Fatalf("Failed to open database: %v", err)
} }
triedb := trie.NewDatabaseWithConfig(chaindb, &trie.Config{ triedb := trie.NewDatabaseWithConfig(chaindb, &trie.Config{
Preimages: ctx.Bool(utils.CachePreimagesFlag.Name), Preimages: ctx.Bool(utils.CachePreimagesFlag.Name),
}) })
@ -215,32 +216,41 @@ func dumpGenesis(ctx *cli.Context) error {
if err := json.NewEncoder(os.Stdout).Encode(genesis); err != nil { if err := json.NewEncoder(os.Stdout).Encode(genesis); err != nil {
utils.Fatalf("could not encode genesis: %s", err) utils.Fatalf("could not encode genesis: %s", err)
} }
return nil return nil
} }
// dump whatever already exists in the datadir // dump whatever already exists in the datadir
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
for _, name := range []string{"chaindata", "lightchaindata"} { for _, name := range []string{"chaindata", "lightchaindata"} {
db, err := stack.OpenDatabase(name, 0, 0, "", true) db, err := stack.OpenDatabase(name, 0, 0, "", true)
if err != nil { if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return err return err
} }
continue continue
} }
genesis, err := core.ReadGenesis(db) genesis, err := core.ReadGenesis(db)
if err != nil { if err != nil {
utils.Fatalf("failed to read genesis: %s", err) utils.Fatalf("failed to read genesis: %s", err)
} }
db.Close() db.Close()
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil { if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
utils.Fatalf("could not encode stored genesis: %s", err) utils.Fatalf("could not encode stored genesis: %s", err)
} }
return nil return nil
} }
if ctx.IsSet(utils.DataDirFlag.Name) { if ctx.IsSet(utils.DataDirFlag.Name) {
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir) utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
} }
utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir") utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir")
return nil return nil
} }
@ -337,6 +347,7 @@ func exportChain(ctx *cli.Context) error {
var err error var err error
fp := ctx.Args().First() fp := ctx.Args().First()
if ctx.Args().Len() < 3 { if ctx.Args().Len() < 3 {
err = utils.ExportChain(chain, fp) err = utils.ExportChain(chain, fp)
} else { } else {
@ -465,6 +476,7 @@ func dump(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
config := &trie.Config{ config := &trie.Config{
Preimages: true, // always enable preimage lookup Preimages: true, // always enable preimage lookup
} }

View file

@ -129,6 +129,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
} }
utils.SetEthConfig(ctx, stack, &cfg.Eth) utils.SetEthConfig(ctx, stack, &cfg.Eth)
if ctx.IsSet(utils.EthStatsURLFlag.Name) { if ctx.IsSet(utils.EthStatsURLFlag.Name) {
cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name) cfg.Ethstats.URL = ctx.String(utils.EthStatsURLFlag.Name)
} }
@ -188,45 +189,59 @@ func dumpConfig(ctx *cli.Context) error {
} }
func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) { func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
if ctx.IsSet(utils.MetricsEnabledFlag.Name) { if ctx.IsSet(utils.MetricsEnabledFlag.Name) {
cfg.Metrics.Enabled = ctx.Bool(utils.MetricsEnabledFlag.Name) cfg.Metrics.Enabled = ctx.Bool(utils.MetricsEnabledFlag.Name)
} }
if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) { if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) {
cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name) cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name)
} }
if ctx.IsSet(utils.MetricsHTTPFlag.Name) { if ctx.IsSet(utils.MetricsHTTPFlag.Name) {
cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name) cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name)
} }
if ctx.IsSet(utils.MetricsPortFlag.Name) { if ctx.IsSet(utils.MetricsPortFlag.Name) {
cfg.Metrics.Port = ctx.Int(utils.MetricsPortFlag.Name) cfg.Metrics.Port = ctx.Int(utils.MetricsPortFlag.Name)
} }
if ctx.IsSet(utils.MetricsEnableInfluxDBFlag.Name) { if ctx.IsSet(utils.MetricsEnableInfluxDBFlag.Name) {
cfg.Metrics.EnableInfluxDB = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name) cfg.Metrics.EnableInfluxDB = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBEndpointFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBEndpointFlag.Name) {
cfg.Metrics.InfluxDBEndpoint = ctx.String(utils.MetricsInfluxDBEndpointFlag.Name) cfg.Metrics.InfluxDBEndpoint = ctx.String(utils.MetricsInfluxDBEndpointFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBDatabaseFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBDatabaseFlag.Name) {
cfg.Metrics.InfluxDBDatabase = ctx.String(utils.MetricsInfluxDBDatabaseFlag.Name) cfg.Metrics.InfluxDBDatabase = ctx.String(utils.MetricsInfluxDBDatabaseFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) {
cfg.Metrics.InfluxDBUsername = ctx.String(utils.MetricsInfluxDBUsernameFlag.Name) cfg.Metrics.InfluxDBUsername = ctx.String(utils.MetricsInfluxDBUsernameFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name) {
cfg.Metrics.InfluxDBPassword = ctx.String(utils.MetricsInfluxDBPasswordFlag.Name) cfg.Metrics.InfluxDBPassword = ctx.String(utils.MetricsInfluxDBPasswordFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) {
cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name) cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name)
} }
if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) { if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name) cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) {
cfg.Metrics.InfluxDBToken = ctx.String(utils.MetricsInfluxDBTokenFlag.Name) cfg.Metrics.InfluxDBToken = ctx.String(utils.MetricsInfluxDBTokenFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name) {
cfg.Metrics.InfluxDBBucket = ctx.String(utils.MetricsInfluxDBBucketFlag.Name) cfg.Metrics.InfluxDBBucket = ctx.String(utils.MetricsInfluxDBBucketFlag.Name)
} }
if ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) { if ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) {
cfg.Metrics.InfluxDBOrganization = ctx.String(utils.MetricsInfluxDBOrganizationFlag.Name) cfg.Metrics.InfluxDBOrganization = ctx.String(utils.MetricsInfluxDBOrganizationFlag.Name)
} }

View file

@ -138,6 +138,7 @@ func remoteConsole(ctx *cli.Context) error {
} }
endpoint = fmt.Sprintf("%s/bor.ipc", path) endpoint = fmt.Sprintf("%s/bor.ipc", path)
} }
client, err := utils.DialRPCWithHeaders(endpoint, ctx.StringSlice(utils.HttpHeaderFlag.Name)) client, err := utils.DialRPCWithHeaders(endpoint, ctx.StringSlice(utils.HttpHeaderFlag.Name))
if err != nil { if err != nil {
utils.Fatalf("Unable to attach to remote geth: %v", err) utils.Fatalf("Unable to attach to remote geth: %v", err)
@ -173,6 +174,7 @@ func ephemeralConsole(ctx *cli.Context) error {
for _, file := range ctx.Args().Slice() { for _, file := range ctx.Args().Slice() {
b.Write([]byte(fmt.Sprintf("loadScript('%s');", file))) b.Write([]byte(fmt.Sprintf("loadScript('%s');", file)))
} }
utils.Fatalf(`The "js" command is deprecated. Please use the following instead: utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
geth --exec "%s" console`, b.String()) geth --exec "%s" console`, b.String())
return nil return nil

View file

@ -291,9 +291,11 @@ func checkStateContent(ctx *cli.Context) error {
prefix []byte prefix []byte
start []byte start []byte
) )
if ctx.NArg() > 1 { if ctx.NArg() > 1 {
return fmt.Errorf("max 1 argument: %v", ctx.Command.ArgsUsage) return fmt.Errorf("max 1 argument: %v", ctx.Command.ArgsUsage)
} }
if ctx.NArg() > 0 { if ctx.NArg() > 0 {
if d, err := hexutil.Decode(ctx.Args().First()); err != nil { if d, err := hexutil.Decode(ctx.Args().First()); err != nil {
return fmt.Errorf("failed to hex-decode 'start': %v", err) return fmt.Errorf("failed to hex-decode 'start': %v", err)
@ -301,11 +303,13 @@ func checkStateContent(ctx *cli.Context) error {
start = d start = d
} }
} }
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
defer stack.Close() defer stack.Close()
db := utils.MakeChainDatabase(ctx, stack, true) db := utils.MakeChainDatabase(ctx, stack, true)
defer db.Close() defer db.Close()
var ( var (
it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32) it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
hasher = crypto.NewKeccakState() hasher = crypto.NewKeccakState()
@ -315,28 +319,37 @@ func checkStateContent(ctx *cli.Context) error {
startTime = time.Now() startTime = time.Now()
lastLog = time.Now() lastLog = time.Now()
) )
for it.Next() { for it.Next() {
count++ count++
k := it.Key() k := it.Key()
v := it.Value() v := it.Value()
hasher.Reset() hasher.Reset()
hasher.Write(v) hasher.Write(v)
hasher.Read(got) hasher.Read(got)
if !bytes.Equal(k, got) { if !bytes.Equal(k, got) {
errs++ errs++
fmt.Printf("Error at %#x\n", k) fmt.Printf("Error at %#x\n", k)
fmt.Printf(" Hash: %#x\n", got) fmt.Printf(" Hash: %#x\n", got)
fmt.Printf(" Data: %#x\n", v) fmt.Printf(" Data: %#x\n", v)
} }
if time.Since(lastLog) > 8*time.Second { if time.Since(lastLog) > 8*time.Second {
log.Info("Iterating the database", "at", fmt.Sprintf("%#x", k), "elapsed", common.PrettyDuration(time.Since(startTime))) log.Info("Iterating the database", "at", fmt.Sprintf("%#x", k), "elapsed", common.PrettyDuration(time.Since(startTime)))
lastLog = time.Now() lastLog = time.Now()
} }
} }
if err := it.Error(); err != nil { if err := it.Error(); err != nil {
return err return err
} }
log.Info("Iterated the state content", "errors", errs, "items", count) log.Info("Iterated the state content", "errors", errs, "items", count)
return nil return nil
} }
@ -454,6 +467,7 @@ func dbPut(ctx *cli.Context) error {
data []byte data []byte
err error err error
) )
key, err = common.ParseHexOrString(ctx.Args().Get(0)) key, err = common.ParseHexOrString(ctx.Args().Get(0))
if err != nil { if err != nil {
log.Info("Could not decode the key", "error", err) log.Info("Could not decode the key", "error", err)
@ -490,30 +504,36 @@ func dbDumpTrie(ctx *cli.Context) error {
max = int64(-1) max = int64(-1)
err error err error
) )
if state, err = hexutil.Decode(ctx.Args().Get(0)); err != nil { if state, err = hexutil.Decode(ctx.Args().Get(0)); err != nil {
log.Info("Could not decode the state root", "error", err) log.Info("Could not decode the state root", "error", err)
return err return err
} }
if account, err = hexutil.Decode(ctx.Args().Get(1)); err != nil { if account, err = hexutil.Decode(ctx.Args().Get(1)); err != nil {
log.Info("Could not decode the account hash", "error", err) log.Info("Could not decode the account hash", "error", err)
return err return err
} }
if storage, err = hexutil.Decode(ctx.Args().Get(2)); err != nil { if storage, err = hexutil.Decode(ctx.Args().Get(2)); err != nil {
log.Info("Could not decode the storage trie root", "error", err) log.Info("Could not decode the storage trie root", "error", err)
return err return err
} }
if ctx.NArg() > 3 { if ctx.NArg() > 3 {
if start, err = hexutil.Decode(ctx.Args().Get(3)); err != nil { if start, err = hexutil.Decode(ctx.Args().Get(3)); err != nil {
log.Info("Could not decode the seek position", "error", err) log.Info("Could not decode the seek position", "error", err)
return err return err
} }
} }
if ctx.NArg() > 4 { if ctx.NArg() > 4 {
if max, err = strconv.ParseInt(ctx.Args().Get(4), 10, 64); err != nil { if max, err = strconv.ParseInt(ctx.Args().Get(4), 10, 64); err != nil {
log.Info("Could not decode the max count", "error", err) log.Info("Could not decode the max count", "error", err)
return err return err
} }
} }
id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage)) id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage))
theTrie, err := trie.New(id, trie.NewDatabase(db)) theTrie, err := trie.New(id, trie.NewDatabase(db))
if err != nil { if err != nil {
@ -536,16 +556,21 @@ func freezerInspect(ctx *cli.Context) error {
if ctx.NArg() < 4 { if ctx.NArg() < 4 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
} }
var ( var (
freezer = ctx.Args().Get(0) freezer = ctx.Args().Get(0)
table = ctx.Args().Get(1) table = ctx.Args().Get(1)
) )
start, err := strconv.ParseInt(ctx.Args().Get(2), 10, 64) start, err := strconv.ParseInt(ctx.Args().Get(2), 10, 64)
if err != nil { if err != nil {
log.Info("Could not read start-param", "err", err) log.Info("Could not read start-param", "err", err)
return err return err
} }
end, err := strconv.ParseInt(ctx.Args().Get(3), 10, 64) end, err := strconv.ParseInt(ctx.Args().Get(3), 10, 64)
if err != nil { if err != nil {
log.Info("Could not read count param", "err", err) log.Info("Could not read count param", "err", err)
return err return err
@ -553,6 +578,7 @@ func freezerInspect(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name)) ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name))
stack.Close() stack.Close()
return rawdb.InspectFreezerTable(ancient, freezer, table, start, end) return rawdb.InspectFreezerTable(ancient, freezer, table, start, end)
} }
@ -694,6 +720,7 @@ func showMetaData(ctx *cli.Context) error {
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err) fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
} }
data := rawdb.ReadChainMetadata(db) data := rawdb.ReadChainMetadata(db)
data = append(data, []string{"frozen", fmt.Sprintf("%d items", ancients)}) data = append(data, []string{"frozen", fmt.Sprintf("%d items", ancients)})
data = append(data, []string{"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))}) data = append(data, []string{"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))})

View file

@ -33,13 +33,17 @@ func TestExport(t *testing.T) {
defer os.Remove(outfile) defer os.Remove(outfile)
geth := runGeth(t, "--datadir", initGeth(t), "export", outfile) geth := runGeth(t, "--datadir", initGeth(t), "export", outfile)
geth.WaitExit() geth.WaitExit()
if have, want := geth.ExitStatus(), 0; have != want { if have, want := geth.ExitStatus(), 0; have != want {
t.Errorf("exit error, have %d want %d", have, want) t.Errorf("exit error, have %d want %d", have, want)
} }
have, err := os.ReadFile(outfile) have, err := os.ReadFile(outfile)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
want := common.FromHex("0xf9026bf90266a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08758259b018f7bce3d2be2ddb62f325eaeea0a0c188cf96623eab468a4413e03a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180837a12008080b875000000000000000000000000000000000000000000000000000000000000000002f0d131f1f97aef08aec6e3291b957d9efe71050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0") want := common.FromHex("0xf9026bf90266a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08758259b018f7bce3d2be2ddb62f325eaeea0a0c188cf96623eab468a4413e03a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180837a12008080b875000000000000000000000000000000000000000000000000000000000000000002f0d131f1f97aef08aec6e3291b957d9efe71050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0")
if !bytes.Equal(have, want) { if !bytes.Equal(have, want) {
t.Fatalf("wrong content exported") t.Fatalf("wrong content exported")

View file

@ -101,6 +101,7 @@ func TestCustomBackend(t *testing.T) {
if strconv.IntSize != 64 { if strconv.IntSize != 64 {
t.Skip("Custom backends are only available on 64-bit platform") t.Skip("Custom backends are only available on 64-bit platform")
} }
genesis := `{ genesis := `{
"alloc" : {}, "alloc" : {},
"coinbase" : "0x0000000000000000000000000000000000000000", "coinbase" : "0x0000000000000000000000000000000000000000",
@ -113,13 +114,16 @@ func TestCustomBackend(t *testing.T) {
"timestamp" : "0x00", "timestamp" : "0x00",
"config" : {} "config" : {}
}` }`
type backendTest struct { type backendTest struct {
initArgs []string initArgs []string
initExpect string initExpect string
execArgs []string execArgs []string
execExpect string execExpect string
} }
testfunc := func(t *testing.T, tt backendTest) error { testfunc := func(t *testing.T, tt backendTest) error {
t.Helper()
// Create a temporary data directory to use and inspect later // Create a temporary data directory to use and inspect later
datadir := t.TempDir() datadir := t.TempDir()
@ -143,8 +147,10 @@ func TestCustomBackend(t *testing.T) {
geth.ExpectRegexp(tt.execExpect) geth.ExpectRegexp(tt.execExpect)
geth.ExpectExit() geth.ExpectExit()
} }
return nil return nil
} }
for i, tt := range []backendTest{ for i, tt := range []backendTest{
{ // When not specified, it should default to leveldb { // When not specified, it should default to leveldb
execArgs: []string{"--db.engine", "leveldb"}, execArgs: []string{"--db.engine", "leveldb"},

View file

@ -473,6 +473,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
// unlockAccounts unlocks any account specifically requested. // unlockAccounts unlocks any account specifically requested.
func unlockAccounts(ctx *cli.Context, stack *node.Node) { func unlockAccounts(ctx *cli.Context, stack *node.Node) {
var unlocks []string var unlocks []string
inputs := strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",") inputs := strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",")
for _, input := range inputs { for _, input := range inputs {
if trimmed := strings.TrimSpace(input); trimmed != "" { if trimmed := strings.TrimSpace(input); trimmed != "" {
@ -488,11 +489,14 @@ func unlockAccounts(ctx *cli.Context, stack *node.Node) {
if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() { if !stack.Config().InsecureUnlockAllowed && stack.Config().ExtRPCEnabled() {
utils.Fatalf("Account unlock with HTTP access is forbidden!") utils.Fatalf("Account unlock with HTTP access is forbidden!")
} }
backends := stack.AccountManager().Backends(keystore.KeyStoreType) backends := stack.AccountManager().Backends(keystore.KeyStoreType)
if len(backends) == 0 { if len(backends) == 0 {
log.Warn("Failed to unlock accounts, keystore is not available") log.Warn("Failed to unlock accounts, keystore is not available")
return return
} }
ks := backends[0].(*keystore.KeyStore) ks := backends[0].(*keystore.KeyStore)
passwords := utils.MakePasswordList(ctx) passwords := utils.MakePasswordList(ctx)
for i, account := range unlocks { for i, account := range unlocks {

View file

@ -131,9 +131,11 @@ func printVersion(ctx *cli.Context) error {
fmt.Println(strings.Title(clientIdentifier)) fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", params.VersionWithMeta) fmt.Println("Version:", params.VersionWithMeta)
if git.Commit != "" { if git.Commit != "" {
fmt.Println("Git Commit:", git.Commit) fmt.Println("Git Commit:", git.Commit)
} }
if git.Date != "" { if git.Date != "" {
fmt.Println("Git Commit Date:", git.Date) fmt.Println("Git Commit Date:", git.Date)
} }

View file

@ -207,6 +207,7 @@ func verifyState(ctx *cli.Context) error {
log.Error("Failed to load head block") log.Error("Failed to load head block")
return errors.New("no head block") return errors.New("no head block")
} }
snapconfig := snapshot.Config{ snapconfig := snapshot.Config{
CacheSize: 256, CacheSize: 256,
Recovery: false, Recovery: false,
@ -235,6 +236,7 @@ func verifyState(ctx *cli.Context) error {
return err return err
} }
log.Info("Verified the state", "root", root) log.Info("Verified the state", "root", root)
return snapshot.CheckDanglingStorage(chaindb) return snapshot.CheckDanglingStorage(chaindb)
} }
@ -300,6 +302,7 @@ func traverseState(ctx *cli.Context) error {
log.Error("Invalid account encountered during traversal", "err", err) log.Error("Invalid account encountered during traversal", "err", err)
return err return err
} }
if acc.Root != types.EmptyRootHash { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root) id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root)
storageTrie, err := trie.NewStateTrie(id, triedb) storageTrie, err := trie.NewStateTrie(id, triedb)
@ -316,6 +319,7 @@ func traverseState(ctx *cli.Context) error {
return storageIter.Err return storageIter.Err
} }
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {
log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash)) log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash))
@ -398,9 +402,11 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Missing trie node(account)", "hash", node) log.Error("Missing trie node(account)", "hash", node)
return errors.New("missing account") return errors.New("missing account")
} }
hasher.Reset() hasher.Reset()
hasher.Write(blob) hasher.Write(blob)
hasher.Read(got) hasher.Read(got)
if !bytes.Equal(got, node.Bytes()) { if !bytes.Equal(got, node.Bytes()) {
log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob) log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob)
return errors.New("invalid account node") return errors.New("invalid account node")
@ -415,6 +421,7 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Invalid account encountered during traversal", "err", err) log.Error("Invalid account encountered during traversal", "err", err)
return errors.New("invalid account") return errors.New("invalid account")
} }
if acc.Root != types.EmptyRootHash { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root) id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root)
storageTrie, err := trie.NewStateTrie(id, triedb) storageTrie, err := trie.NewStateTrie(id, triedb)
@ -435,9 +442,11 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Missing trie node(storage)", "hash", node) log.Error("Missing trie node(storage)", "hash", node)
return errors.New("missing storage") return errors.New("missing storage")
} }
hasher.Reset() hasher.Reset()
hasher.Write(blob) hasher.Write(blob)
hasher.Read(got) hasher.Read(got)
if !bytes.Equal(got, node.Bytes()) { if !bytes.Equal(got, node.Bytes()) {
log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob) log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob)
return errors.New("invalid storage node") return errors.New("invalid storage node")
@ -453,6 +462,7 @@ func traverseRawState(ctx *cli.Context) error {
return storageIter.Error() return storageIter.Error()
} }
} }
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {
log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey())) log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey()))
@ -490,6 +500,7 @@ func dumpState(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
snapConfig := snapshot.Config{ snapConfig := snapshot.Config{
CacheSize: 256, CacheSize: 256,
Recovery: false, Recovery: false,
@ -528,6 +539,7 @@ func dumpState(ctx *cli.Context) error {
CodeHash: account.CodeHash, CodeHash: account.CodeHash,
SecureKey: accIt.Hash().Bytes(), SecureKey: accIt.Hash().Bytes(),
} }
if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) { if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash)) da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash))
} }
@ -564,10 +576,12 @@ func checkAccount(ctx *cli.Context) error {
if ctx.NArg() != 1 { if ctx.NArg() != 1 {
return errors.New("need <address|hash> arg") return errors.New("need <address|hash> arg")
} }
var ( var (
hash common.Hash hash common.Hash
addr common.Address addr common.Address
) )
switch arg := ctx.Args().First(); len(arg) { switch arg := ctx.Args().First(); len(arg) {
case 40, 42: case 40, 42:
addr = common.HexToAddress(arg) addr = common.HexToAddress(arg)
@ -577,15 +591,22 @@ func checkAccount(ctx *cli.Context) error {
default: default:
return errors.New("malformed address or hash") return errors.New("malformed address or hash")
} }
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
defer stack.Close() defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true) chaindb := utils.MakeChainDatabase(ctx, stack, true)
defer chaindb.Close() defer chaindb.Close()
start := time.Now() start := time.Now()
log.Info("Checking difflayer journal", "address", addr, "hash", hash) log.Info("Checking difflayer journal", "address", addr, "hash", hash)
if err := snapshot.CheckJournalAccount(chaindb, hash); err != nil { if err := snapshot.CheckJournalAccount(chaindb, hash); err != nil {
return err return err
} }
log.Info("Checked the snapshot journalled storage", "time", common.PrettyDuration(time.Since(start))) log.Info("Checked the snapshot journalled storage", "time", common.PrettyDuration(time.Since(start)))
return nil return nil
} }

View file

@ -77,9 +77,11 @@ func checkChildren(root verkle.VerkleNode, resolver verkle.NodeResolverFn) error
childC := child.ComputeCommitment().Bytes() childC := child.ComputeCommitment().Bytes()
childS, err := resolver(childC[:]) childS, err := resolver(childC[:])
if bytes.Equal(childC[:], zero[:]) { if bytes.Equal(childC[:], zero[:]) {
continue continue
} }
if err != nil { if err != nil {
return fmt.Errorf("could not find child %x in db: %w", childC, err) return fmt.Errorf("could not find child %x in db: %w", childC, err)
} }
@ -88,18 +90,19 @@ func checkChildren(root verkle.VerkleNode, resolver verkle.NodeResolverFn) error
if err != nil { if err != nil {
return fmt.Errorf("decode error child %x in db: %w", child.ComputeCommitment().Bytes(), err) return fmt.Errorf("decode error child %x in db: %w", child.ComputeCommitment().Bytes(), err)
} }
if err := checkChildren(childN, resolver); err != nil { if err := checkChildren(childN, resolver); err != nil {
return fmt.Errorf("%x%w", i, err) // write the path to the erroring node return fmt.Errorf("%x%w", i, err) // write the path to the erroring node
} }
} }
case *verkle.LeafNode: case *verkle.LeafNode:
// sanity check: ensure at least one value is non-zero // sanity check: ensure at least one value is non-zero
for i := 0; i < verkle.NodeWidth; i++ { for i := 0; i < verkle.NodeWidth; i++ {
if len(node.Value(i)) != 0 { if len(node.Value(i)) != 0 {
return nil return nil
} }
} }
return fmt.Errorf("Both balance and nonce are 0") return fmt.Errorf("Both balance and nonce are 0")
case verkle.Empty: case verkle.Empty:
// nothing to do // nothing to do
@ -116,24 +119,29 @@ func verifyVerkle(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, true) chaindb := utils.MakeChainDatabase(ctx, stack, true)
headBlock := rawdb.ReadHeadBlock(chaindb) headBlock := rawdb.ReadHeadBlock(chaindb)
if headBlock == nil { if headBlock == nil {
log.Error("Failed to load head block") log.Error("Failed to load head block")
return errors.New("no head block") return errors.New("no head block")
} }
if ctx.NArg() > 1 { if ctx.NArg() > 1 {
log.Error("Too many arguments given") log.Error("Too many arguments given")
return errors.New("too many arguments") return errors.New("too many arguments")
} }
var ( var (
rootC common.Hash rootC common.Hash
err error err error
) )
if ctx.NArg() == 1 { if ctx.NArg() == 1 {
rootC, err = parseRoot(ctx.Args().First()) rootC, err = parseRoot(ctx.Args().First())
if err != nil { if err != nil {
log.Error("Failed to resolve state root", "error", err) log.Error("Failed to resolve state root", "error", err)
return err return err
} }
log.Info("Rebuilding the tree", "root", rootC) log.Info("Rebuilding the tree", "root", rootC)
} else { } else {
rootC = headBlock.Root() rootC = headBlock.Root()
@ -144,7 +152,9 @@ func verifyVerkle(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
root, err := verkle.ParseNode(serializedRoot, 0, rootC[:]) root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
if err != nil { if err != nil {
return err return err
} }
@ -155,6 +165,7 @@ func verifyVerkle(ctx *cli.Context) error {
} }
log.Info("Tree was rebuilt from the database") log.Info("Tree was rebuilt from the database")
return nil return nil
} }
@ -163,27 +174,34 @@ func expandVerkle(ctx *cli.Context) error {
defer stack.Close() defer stack.Close()
chaindb := utils.MakeChainDatabase(ctx, stack, true) chaindb := utils.MakeChainDatabase(ctx, stack, true)
var ( var (
rootC common.Hash rootC common.Hash
keylist [][]byte keylist [][]byte
err error err error
) )
if ctx.NArg() >= 2 { if ctx.NArg() >= 2 {
rootC, err = parseRoot(ctx.Args().First()) rootC, err = parseRoot(ctx.Args().First())
if err != nil { if err != nil {
log.Error("Failed to resolve state root", "error", err) log.Error("Failed to resolve state root", "error", err)
return err return err
} }
keylist = make([][]byte, 0, ctx.Args().Len()-1) keylist = make([][]byte, 0, ctx.Args().Len()-1)
args := ctx.Args().Slice() args := ctx.Args().Slice()
for i := range args[1:] { for i := range args[1:] {
key, err := hex.DecodeString(args[i+1]) key, err := hex.DecodeString(args[i+1])
log.Info("decoded key", "arg", args[i+1], "key", key) log.Info("decoded key", "arg", args[i+1], "key", key)
if err != nil { if err != nil {
return fmt.Errorf("error decoding key #%d: %w", i+1, err) return fmt.Errorf("error decoding key #%d: %w", i+1, err)
} }
keylist = append(keylist, key) keylist = append(keylist, key)
} }
log.Info("Rebuilding the tree", "root", rootC) log.Info("Rebuilding the tree", "root", rootC)
} else { } else {
return fmt.Errorf("usage: %s root key1 [key 2...]", ctx.App.Name) return fmt.Errorf("usage: %s root key1 [key 2...]", ctx.App.Name)
@ -193,7 +211,9 @@ func expandVerkle(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
root, err := verkle.ParseNode(serializedRoot, 0, rootC[:]) root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
if err != nil { if err != nil {
return err return err
} }
@ -208,5 +228,6 @@ func expandVerkle(ctx *cli.Context) error {
} else { } else {
log.Info("Tree was dumped to file", "file", "dump.dot") log.Info("Tree was dumped to file", "file", "dump.dot")
} }
return nil return nil
} }

View file

@ -131,6 +131,7 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritica
} else if freeSpace < 2*freeDiskSpaceCritical { } else if freeSpace < 2*freeDiskSpaceCritical {
log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical), "path", path) log.Warn("Disk space is running low. Geth will shutdown if disk space runs below critical level.", "available", common.StorageSize(freeSpace), "critical_level", common.StorageSize(freeDiskSpaceCritical), "path", path)
} }
time.Sleep(30 * time.Second) time.Sleep(30 * time.Second)
} }
} }

View file

@ -1037,6 +1037,7 @@ func MakeDataDir(ctx *cli.Context) string {
if ctx.Bool(GoerliFlag.Name) { if ctx.Bool(GoerliFlag.Name) {
return filepath.Join(path, "goerli") return filepath.Join(path, "goerli")
} }
if ctx.Bool(SepoliaFlag.Name) { if ctx.Bool(SepoliaFlag.Name) {
return filepath.Join(path, "sepolia") return filepath.Join(path, "sepolia")
} }
@ -1140,6 +1141,7 @@ func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
if ctx.IsSet(ListenPortFlag.Name) { if ctx.IsSet(ListenPortFlag.Name) {
cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name)) cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name))
} }
if ctx.IsSet(DiscoveryPortFlag.Name) { if ctx.IsSet(DiscoveryPortFlag.Name) {
cfg.DiscAddr = fmt.Sprintf(":%d", ctx.Int(DiscoveryPortFlag.Name)) cfg.DiscAddr = fmt.Sprintf(":%d", ctx.Int(DiscoveryPortFlag.Name))
} }
@ -1209,6 +1211,7 @@ func setHTTP(ctx *cli.Context, cfg *node.Config) {
if ctx.IsSet(HTTPPathPrefixFlag.Name) { if ctx.IsSet(HTTPPathPrefixFlag.Name) {
cfg.HTTPPathPrefix = ctx.String(HTTPPathPrefixFlag.Name) cfg.HTTPPathPrefix = ctx.String(HTTPPathPrefixFlag.Name)
} }
if ctx.IsSet(AllowUnprotectedTxs.Name) { if ctx.IsSet(AllowUnprotectedTxs.Name) {
cfg.AllowUnprotectedTxs = ctx.Bool(AllowUnprotectedTxs.Name) cfg.AllowUnprotectedTxs = ctx.Bool(AllowUnprotectedTxs.Name)
} }
@ -1220,6 +1223,7 @@ func setGraphQL(ctx *cli.Context, cfg *node.Config) {
if ctx.IsSet(GraphQLCORSDomainFlag.Name) { if ctx.IsSet(GraphQLCORSDomainFlag.Name) {
cfg.GraphQLCors = SplitAndTrim(ctx.String(GraphQLCORSDomainFlag.Name)) cfg.GraphQLCors = SplitAndTrim(ctx.String(GraphQLCORSDomainFlag.Name))
} }
if ctx.IsSet(GraphQLVirtualHostsFlag.Name) { if ctx.IsSet(GraphQLVirtualHostsFlag.Name) {
cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.String(GraphQLVirtualHostsFlag.Name)) cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.String(GraphQLVirtualHostsFlag.Name))
} }
@ -1234,6 +1238,7 @@ func setWS(ctx *cli.Context, cfg *node.Config) {
cfg.WSHost = ctx.String(WSListenAddrFlag.Name) cfg.WSHost = ctx.String(WSListenAddrFlag.Name)
} }
} }
if ctx.IsSet(WSPortFlag.Name) { if ctx.IsSet(WSPortFlag.Name) {
cfg.WSPort = ctx.Int(WSPortFlag.Name) cfg.WSPort = ctx.Int(WSPortFlag.Name)
} }
@ -1268,31 +1273,40 @@ func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(LightServeFlag.Name) { if ctx.IsSet(LightServeFlag.Name) {
cfg.LightServ = ctx.Int(LightServeFlag.Name) cfg.LightServ = ctx.Int(LightServeFlag.Name)
} }
if ctx.IsSet(LightIngressFlag.Name) { if ctx.IsSet(LightIngressFlag.Name) {
cfg.LightIngress = ctx.Int(LightIngressFlag.Name) cfg.LightIngress = ctx.Int(LightIngressFlag.Name)
} }
if ctx.IsSet(LightEgressFlag.Name) { if ctx.IsSet(LightEgressFlag.Name) {
cfg.LightEgress = ctx.Int(LightEgressFlag.Name) cfg.LightEgress = ctx.Int(LightEgressFlag.Name)
} }
if ctx.IsSet(LightMaxPeersFlag.Name) { if ctx.IsSet(LightMaxPeersFlag.Name) {
cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name) cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name)
} }
if ctx.IsSet(UltraLightServersFlag.Name) { if ctx.IsSet(UltraLightServersFlag.Name) {
cfg.UltraLightServers = strings.Split(ctx.String(UltraLightServersFlag.Name), ",") cfg.UltraLightServers = strings.Split(ctx.String(UltraLightServersFlag.Name), ",")
} }
if ctx.IsSet(UltraLightFractionFlag.Name) { if ctx.IsSet(UltraLightFractionFlag.Name) {
cfg.UltraLightFraction = ctx.Int(UltraLightFractionFlag.Name) cfg.UltraLightFraction = ctx.Int(UltraLightFractionFlag.Name)
} }
if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 { if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 {
log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", ethconfig.Defaults.UltraLightFraction) log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", ethconfig.Defaults.UltraLightFraction)
cfg.UltraLightFraction = ethconfig.Defaults.UltraLightFraction cfg.UltraLightFraction = ethconfig.Defaults.UltraLightFraction
} }
if ctx.IsSet(UltraLightOnlyAnnounceFlag.Name) { if ctx.IsSet(UltraLightOnlyAnnounceFlag.Name) {
cfg.UltraLightOnlyAnnounce = ctx.Bool(UltraLightOnlyAnnounceFlag.Name) cfg.UltraLightOnlyAnnounce = ctx.Bool(UltraLightOnlyAnnounceFlag.Name)
} }
if ctx.IsSet(LightNoPruneFlag.Name) { if ctx.IsSet(LightNoPruneFlag.Name) {
cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name) cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name)
} }
if ctx.IsSet(LightNoSyncServeFlag.Name) { if ctx.IsSet(LightNoSyncServeFlag.Name) {
cfg.LightNoSyncServe = ctx.Bool(LightNoSyncServeFlag.Name) cfg.LightNoSyncServe = ctx.Bool(LightNoSyncServeFlag.Name)
} }
@ -1355,15 +1369,20 @@ func setEtherbase(ctx *cli.Context, cfg *ethconfig.Config) {
if !ctx.IsSet(MinerEtherbaseFlag.Name) { if !ctx.IsSet(MinerEtherbaseFlag.Name) {
return return
} }
addr := ctx.String(MinerEtherbaseFlag.Name) addr := ctx.String(MinerEtherbaseFlag.Name)
if strings.HasPrefix(addr, "0x") || strings.HasPrefix(addr, "0X") { if strings.HasPrefix(addr, "0x") || strings.HasPrefix(addr, "0X") {
addr = addr[2:] addr = addr[2:]
} }
b, err := hex.DecodeString(addr) b, err := hex.DecodeString(addr)
if err != nil || len(b) != common.AddressLength { if err != nil || len(b) != common.AddressLength {
Fatalf("-%s: invalid etherbase address %q", MinerEtherbaseFlag.Name, addr) Fatalf("-%s: invalid etherbase address %q", MinerEtherbaseFlag.Name, addr)
return return
} }
cfg.Miner.Etherbase = common.BytesToAddress(b) cfg.Miner.Etherbase = common.BytesToAddress(b)
} }
@ -1373,6 +1392,7 @@ func MakePasswordList(ctx *cli.Context) []string {
if path == "" { if path == "" {
return nil return nil
} }
text, err := os.ReadFile(path) text, err := os.ReadFile(path)
if err != nil { if err != nil {
Fatalf("Failed to read password file: %v", err) Fatalf("Failed to read password file: %v", err)
@ -1426,6 +1446,7 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
if ctx.IsSet(MaxPendingPeersFlag.Name) { if ctx.IsSet(MaxPendingPeersFlag.Name) {
cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name) cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name)
} }
if ctx.IsSet(NoDiscoverFlag.Name) || lightClient { if ctx.IsSet(NoDiscoverFlag.Name) || lightClient {
cfg.NoDiscovery = true cfg.NoDiscovery = true
} }
@ -1434,6 +1455,7 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
// unless it is explicitly disabled with --nodiscover note that explicitly specifying // unless it is explicitly disabled with --nodiscover note that explicitly specifying
// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
forceV5Discovery := (lightClient || lightServer) && !ctx.Bool(NoDiscoverFlag.Name) forceV5Discovery := (lightClient || lightServer) && !ctx.Bool(NoDiscoverFlag.Name)
if ctx.IsSet(DiscoveryV5Flag.Name) { if ctx.IsSet(DiscoveryV5Flag.Name) {
cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name) cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name)
} else if forceV5Discovery { } else if forceV5Discovery {
@ -1484,26 +1506,33 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
if ctx.IsSet(KeyStoreDirFlag.Name) { if ctx.IsSet(KeyStoreDirFlag.Name) {
cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name) cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name)
} }
if ctx.IsSet(DeveloperFlag.Name) { if ctx.IsSet(DeveloperFlag.Name) {
cfg.UseLightweightKDF = true cfg.UseLightweightKDF = true
} }
if ctx.IsSet(LightKDFFlag.Name) { if ctx.IsSet(LightKDFFlag.Name) {
cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name) cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name)
} }
if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB { if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB {
log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable") log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable")
} }
if ctx.IsSet(USBFlag.Name) { if ctx.IsSet(USBFlag.Name) {
cfg.USB = ctx.Bool(USBFlag.Name) cfg.USB = ctx.Bool(USBFlag.Name)
} }
if ctx.IsSet(InsecureUnlockAllowedFlag.Name) { if ctx.IsSet(InsecureUnlockAllowedFlag.Name) {
cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name) cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name)
} }
if ctx.IsSet(DBEngineFlag.Name) { if ctx.IsSet(DBEngineFlag.Name) {
dbEngine := ctx.String(DBEngineFlag.Name) dbEngine := ctx.String(DBEngineFlag.Name)
if dbEngine != "leveldb" && dbEngine != "pebble" { if dbEngine != "leveldb" && dbEngine != "pebble" {
Fatalf("Invalid choice for db.engine '%s', allowed 'leveldb' or 'pebble'", dbEngine) Fatalf("Invalid choice for db.engine '%s', allowed 'leveldb' or 'pebble'", dbEngine)
} }
log.Info(fmt.Sprintf("Using %s as db engine", dbEngine)) log.Info(fmt.Sprintf("Using %s as db engine", dbEngine))
cfg.DBEngine = dbEngine cfg.DBEngine = dbEngine
} }
@ -1517,10 +1546,12 @@ func setSmartCard(ctx *cli.Context, cfg *node.Config) {
} }
// Sanity check that the smartcard path is valid // Sanity check that the smartcard path is valid
fi, err := os.Stat(path) fi, err := os.Stat(path)
if err != nil { if err != nil {
log.Info("Smartcard socket not found, disabling", "err", err) log.Info("Smartcard socket not found, disabling", "err", err)
return return
} }
if fi.Mode()&os.ModeType != os.ModeSocket { if fi.Mode()&os.ModeType != os.ModeSocket {
log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String()) log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
return return
@ -1548,15 +1579,19 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
if light { if light {
*cfg = ethconfig.LightClientGPO *cfg = ethconfig.LightClientGPO
} }
if ctx.IsSet(GpoBlocksFlag.Name) { if ctx.IsSet(GpoBlocksFlag.Name) {
cfg.Blocks = ctx.Int(GpoBlocksFlag.Name) cfg.Blocks = ctx.Int(GpoBlocksFlag.Name)
} }
if ctx.IsSet(GpoPercentileFlag.Name) { if ctx.IsSet(GpoPercentileFlag.Name) {
cfg.Percentile = ctx.Int(GpoPercentileFlag.Name) cfg.Percentile = ctx.Int(GpoPercentileFlag.Name)
} }
if ctx.IsSet(GpoMaxGasPriceFlag.Name) { if ctx.IsSet(GpoMaxGasPriceFlag.Name) {
cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name)) cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name))
} }
if ctx.IsSet(GpoIgnoreGasPriceFlag.Name) { if ctx.IsSet(GpoIgnoreGasPriceFlag.Name) {
cfg.IgnorePrice = big.NewInt(ctx.Int64(GpoIgnoreGasPriceFlag.Name)) cfg.IgnorePrice = big.NewInt(ctx.Int64(GpoIgnoreGasPriceFlag.Name))
} }
@ -1573,33 +1608,43 @@ func setTxPool(ctx *cli.Context, cfg *txpool.Config) {
} }
} }
} }
if ctx.IsSet(TxPoolNoLocalsFlag.Name) { if ctx.IsSet(TxPoolNoLocalsFlag.Name) {
cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name) cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name)
} }
if ctx.IsSet(TxPoolJournalFlag.Name) { if ctx.IsSet(TxPoolJournalFlag.Name) {
cfg.Journal = ctx.String(TxPoolJournalFlag.Name) cfg.Journal = ctx.String(TxPoolJournalFlag.Name)
} }
if ctx.IsSet(TxPoolRejournalFlag.Name) { if ctx.IsSet(TxPoolRejournalFlag.Name) {
cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name) cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name)
} }
if ctx.IsSet(TxPoolPriceLimitFlag.Name) { if ctx.IsSet(TxPoolPriceLimitFlag.Name) {
cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name) cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name)
} }
if ctx.IsSet(TxPoolPriceBumpFlag.Name) { if ctx.IsSet(TxPoolPriceBumpFlag.Name) {
cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name) cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name)
} }
if ctx.IsSet(TxPoolAccountSlotsFlag.Name) { if ctx.IsSet(TxPoolAccountSlotsFlag.Name) {
cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name) cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name)
} }
if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) { if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) {
cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name) cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name)
} }
if ctx.IsSet(TxPoolAccountQueueFlag.Name) { if ctx.IsSet(TxPoolAccountQueueFlag.Name) {
cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name) cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name)
} }
if ctx.IsSet(TxPoolGlobalQueueFlag.Name) { if ctx.IsSet(TxPoolGlobalQueueFlag.Name) {
cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name) cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name)
} }
if ctx.IsSet(TxPoolLifetimeFlag.Name) { if ctx.IsSet(TxPoolLifetimeFlag.Name) {
cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name) cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name)
} }
@ -1609,24 +1654,31 @@ func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
if ctx.IsSet(EthashCacheDirFlag.Name) { if ctx.IsSet(EthashCacheDirFlag.Name) {
cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name) cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name)
} }
if ctx.IsSet(EthashDatasetDirFlag.Name) { if ctx.IsSet(EthashDatasetDirFlag.Name) {
cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name) cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name)
} }
if ctx.IsSet(EthashCachesInMemoryFlag.Name) { if ctx.IsSet(EthashCachesInMemoryFlag.Name) {
cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name) cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name)
} }
if ctx.IsSet(EthashCachesOnDiskFlag.Name) { if ctx.IsSet(EthashCachesOnDiskFlag.Name) {
cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name) cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name)
} }
if ctx.IsSet(EthashCachesLockMmapFlag.Name) { if ctx.IsSet(EthashCachesLockMmapFlag.Name) {
cfg.Ethash.CachesLockMmap = ctx.Bool(EthashCachesLockMmapFlag.Name) cfg.Ethash.CachesLockMmap = ctx.Bool(EthashCachesLockMmapFlag.Name)
} }
if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) { if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) {
cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name) cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name)
} }
if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) { if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) {
cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name) cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name)
} }
if ctx.IsSet(EthashDatasetsLockMmapFlag.Name) { if ctx.IsSet(EthashDatasetsLockMmapFlag.Name) {
cfg.Ethash.DatasetsLockMmap = ctx.Bool(EthashDatasetsLockMmapFlag.Name) cfg.Ethash.DatasetsLockMmap = ctx.Bool(EthashDatasetsLockMmapFlag.Name)
} }
@ -1636,22 +1688,29 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
if ctx.IsSet(MinerNotifyFlag.Name) { if ctx.IsSet(MinerNotifyFlag.Name) {
cfg.Notify = strings.Split(ctx.String(MinerNotifyFlag.Name), ",") cfg.Notify = strings.Split(ctx.String(MinerNotifyFlag.Name), ",")
} }
cfg.NotifyFull = ctx.Bool(MinerNotifyFullFlag.Name) cfg.NotifyFull = ctx.Bool(MinerNotifyFullFlag.Name)
if ctx.IsSet(MinerExtraDataFlag.Name) { if ctx.IsSet(MinerExtraDataFlag.Name) {
cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name)) cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name))
} }
if ctx.IsSet(MinerGasLimitFlag.Name) { if ctx.IsSet(MinerGasLimitFlag.Name) {
cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name) cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name)
} }
if ctx.IsSet(MinerGasPriceFlag.Name) { if ctx.IsSet(MinerGasPriceFlag.Name) {
cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name) cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name)
} }
if ctx.IsSet(MinerRecommitIntervalFlag.Name) { if ctx.IsSet(MinerRecommitIntervalFlag.Name) {
cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name) cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
} }
if ctx.IsSet(MinerNoVerifyFlag.Name) { if ctx.IsSet(MinerNoVerifyFlag.Name) {
cfg.Noverify = ctx.Bool(MinerNoVerifyFlag.Name) cfg.Noverify = ctx.Bool(MinerNoVerifyFlag.Name)
} }
if ctx.IsSet(MinerNewPayloadTimeout.Name) { if ctx.IsSet(MinerNewPayloadTimeout.Name) {
cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name) cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name)
} }
@ -1662,12 +1721,15 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
if requiredBlocks == "" { if requiredBlocks == "" {
if ctx.IsSet(LegacyWhitelistFlag.Name) { if ctx.IsSet(LegacyWhitelistFlag.Name) {
log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks") log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks")
requiredBlocks = ctx.String(LegacyWhitelistFlag.Name) requiredBlocks = ctx.String(LegacyWhitelistFlag.Name)
} else { } else {
return return
} }
} }
cfg.RequiredBlocks = make(map[uint64]common.Hash) cfg.RequiredBlocks = make(map[uint64]common.Hash)
for _, entry := range strings.Split(requiredBlocks, ",") { for _, entry := range strings.Split(requiredBlocks, ",") {
parts := strings.Split(entry, "=") parts := strings.Split(entry, "=")
if len(parts) != 2 { if len(parts) != 2 {
@ -1681,6 +1743,7 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
if err = hash.UnmarshalText([]byte(parts[1])); err != nil { if err = hash.UnmarshalText([]byte(parts[1])); err != nil {
Fatalf("Invalid required block hash %s: %v", parts[1], err) Fatalf("Invalid required block hash %s: %v", parts[1], err)
} }
cfg.RequiredBlocks[number] = hash cfg.RequiredBlocks[number] = hash
} }
} }
@ -1736,9 +1799,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
ctx.Set(TxLookupLimitFlag.Name, "0") ctx.Set(TxLookupLimitFlag.Name, "0")
log.Warn("Disable transaction unindexing for archive node") log.Warn("Disable transaction unindexing for archive node")
} }
if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 { if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited") log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
} }
setEtherbase(ctx, cfg) setEtherbase(ctx, cfg)
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light") setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
setTxPool(ctx, &cfg.TxPool) setTxPool(ctx, &cfg.TxPool)
@ -1755,6 +1820,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
mem.Total = 2 * 1024 * 1024 * 1024 mem.Total = 2 * 1024 * 1024 * 1024
} }
allowance := int(mem.Total / 1024 / 1024 / 3) allowance := int(mem.Total / 1024 / 1024 / 3)
if cache := ctx.Int(CacheFlag.Name); cache > allowance { if cache := ctx.Int(CacheFlag.Name); cache > allowance {
log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance) log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
ctx.Set(CacheFlag.Name, strconv.Itoa(allowance)) ctx.Set(CacheFlag.Name, strconv.Itoa(allowance))
@ -1770,13 +1836,17 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(SyncModeFlag.Name) { if ctx.IsSet(SyncModeFlag.Name) {
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
} }
if ctx.IsSet(NetworkIdFlag.Name) { if ctx.IsSet(NetworkIdFlag.Name) {
cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name) cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name)
} }
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) {
cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
} }
cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
if ctx.IsSet(AncientFlag.Name) { if ctx.IsSet(AncientFlag.Name) {
cfg.DatabaseFreezer = ctx.String(AncientFlag.Name) cfg.DatabaseFreezer = ctx.String(AncientFlag.Name)
} }
@ -1784,39 +1854,50 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
if ctx.IsSet(GCModeFlag.Name) { if ctx.IsSet(GCModeFlag.Name) {
cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive" cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive"
} }
if ctx.IsSet(CacheNoPrefetchFlag.Name) { if ctx.IsSet(CacheNoPrefetchFlag.Name) {
cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name) cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name)
} }
// Read the value from the flag no matter if it's set or not. // Read the value from the flag no matter if it's set or not.
cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name) cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name)
if cfg.NoPruning && !cfg.Preimages { if cfg.NoPruning && !cfg.Preimages {
cfg.Preimages = true cfg.Preimages = true
log.Info("Enabling recording of key preimages since archive mode is used") log.Info("Enabling recording of key preimages since archive mode is used")
} }
if ctx.IsSet(TxLookupLimitFlag.Name) { if ctx.IsSet(TxLookupLimitFlag.Name) {
cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name) cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name)
} }
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
} }
if ctx.IsSet(CacheTrieJournalFlag.Name) { if ctx.IsSet(CacheTrieJournalFlag.Name) {
cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name) cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name)
} }
if ctx.IsSet(CacheTrieRejournalFlag.Name) { if ctx.IsSet(CacheTrieRejournalFlag.Name) {
cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name) cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name)
} }
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
} }
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100 cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
} }
if ctx.IsSet(CacheLogSizeFlag.Name) { if ctx.IsSet(CacheLogSizeFlag.Name) {
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name) cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
} }
if !ctx.Bool(SnapshotFlag.Name) { if !ctx.Bool(SnapshotFlag.Name) {
// If snap-sync is requested, this flag is also required // If snap-sync is requested, this flag is also required
if cfg.SyncMode == downloader.SnapSync { if cfg.SyncMode == downloader.SnapSync {
@ -1826,9 +1907,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.SnapshotCache = 0 // Disabled cfg.SnapshotCache = 0 // Disabled
} }
} }
if ctx.IsSet(DocRootFlag.Name) { if ctx.IsSet(DocRootFlag.Name) {
cfg.DocRoot = ctx.String(DocRootFlag.Name) cfg.DocRoot = ctx.String(DocRootFlag.Name)
} }
if ctx.IsSet(VMEnableDebugFlag.Name) { if ctx.IsSet(VMEnableDebugFlag.Name) {
// TODO(fjl): force-enable this in --dev mode // TODO(fjl): force-enable this in --dev mode
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name) cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
@ -1842,12 +1925,15 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
} else { } else {
log.Info("Global gas cap disabled") log.Info("Global gas cap disabled")
} }
if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) { if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) {
cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name) cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name)
} }
if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) { if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) {
cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name) cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name)
} }
if ctx.IsSet(NoDiscoverFlag.Name) { if ctx.IsSet(NoDiscoverFlag.Name) {
cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{} cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{}
} else if ctx.IsSet(DNSDiscoveryFlag.Name) { } else if ctx.IsSet(DNSDiscoveryFlag.Name) {
@ -1902,6 +1988,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore) ks = keystores[0].(*keystore.KeyStore)
} }
if ks == nil { if ks == nil {
Fatalf("Keystore is not available") Fatalf("Keystore is not available")
} }
@ -1929,6 +2016,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// Create a new developer genesis block or reuse existing one // Create a new developer genesis block or reuse existing one
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address) cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
if ctx.IsSet(DataDirFlag.Name) { if ctx.IsSet(DataDirFlag.Name) {
// If datadir doesn't exist we need to open db in write-mode // If datadir doesn't exist we need to open db in write-mode
// so leveldb can create files. // so leveldb can create files.
@ -1944,6 +2032,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
} }
chaindb.Close() chaindb.Close()
} }
if !ctx.IsSet(MinerGasPriceFlag.Name) { if !ctx.IsSet(MinerGasPriceFlag.Name) {
cfg.Miner.GasPrice = big.NewInt(1) cfg.Miner.GasPrice = big.NewInt(1)
} }
@ -1980,6 +2069,7 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
Fatalf("Failed to register the Ethereum service: %v", err) Fatalf("Failed to register the Ethereum service: %v", err)
} }
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend)) stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
if err := lescatalyst.Register(stack, backend); err != nil { if err := lescatalyst.Register(stack, backend); err != nil {
Fatalf("Failed to register the Engine API service: %v", err) Fatalf("Failed to register the Engine API service: %v", err)
} }
@ -1995,6 +2085,7 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
Fatalf("Failed to create the LES server: %v", err) Fatalf("Failed to create the LES server: %v", err)
} }
} }
if err := ethcatalyst.Register(stack, backend); err != nil { if err := ethcatalyst.Register(stack, backend); err != nil {
Fatalf("Failed to register the Engine API service: %v", err) Fatalf("Failed to register the Engine API service: %v", err)
} }
@ -2023,10 +2114,12 @@ func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconf
filterSystem := filters.NewFilterSystem(backend, filters.Config{ filterSystem := filters.NewFilterSystem(backend, filters.Config{
LogCacheSize: ethcfg.FilterLogCacheSize, LogCacheSize: ethcfg.FilterLogCacheSize,
}) })
stack.RegisterAPIs([]rpc.API{{ stack.RegisterAPIs([]rpc.API{{
Namespace: "eth", Namespace: "eth",
Service: filters.NewFilterAPI(filterSystem, isLightClient, ethconfig.Defaults.BorLogs), Service: filters.NewFilterAPI(filterSystem, isLightClient, ethconfig.Defaults.BorLogs),
}}) }})
return filterSystem return filterSystem
} }
@ -2036,11 +2129,15 @@ func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, path string) {
if err != nil { if err != nil {
Fatalf("Failed to read block file: %v", err) Fatalf("Failed to read block file: %v", err)
} }
rlpBlob, err := hexutil.Decode(string(bytes.TrimRight(blob, "\r\n"))) rlpBlob, err := hexutil.Decode(string(bytes.TrimRight(blob, "\r\n")))
if err != nil { if err != nil {
Fatalf("Failed to decode block blob: %v", err) Fatalf("Failed to decode block blob: %v", err)
} }
var block types.Block var block types.Block
if err := rlp.DecodeBytes(rlpBlob, &block); err != nil { if err := rlp.DecodeBytes(rlpBlob, &block); err != nil {
Fatalf("Failed to decode block: %v", err) Fatalf("Failed to decode block: %v", err)
} }
@ -2135,13 +2232,16 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
err error err error
chainDb ethdb.Database chainDb ethdb.Database
) )
switch { switch {
case ctx.IsSet(RemoteDBFlag.Name): case ctx.IsSet(RemoteDBFlag.Name):
log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name), "headers", len(ctx.StringSlice(HttpHeaderFlag.Name))) log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name), "headers", len(ctx.StringSlice(HttpHeaderFlag.Name)))
client, err := DialRPCWithHeaders(ctx.String(RemoteDBFlag.Name), ctx.StringSlice(HttpHeaderFlag.Name)) client, err := DialRPCWithHeaders(ctx.String(RemoteDBFlag.Name), ctx.StringSlice(HttpHeaderFlag.Name))
if err != nil { if err != nil {
break break
} }
chainDb = remotedb.New(client) chainDb = remotedb.New(client)
case ctx.String(SyncModeFlag.Name) == "light": case ctx.String(SyncModeFlag.Name) == "light":
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly) chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
@ -2161,6 +2261,7 @@ func IsNetworkPreset(ctx *cli.Context) bool {
return true return true
} }
} }
return false return false
} }
@ -2168,23 +2269,30 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
if endpoint == "" { if endpoint == "" {
return nil, errors.New("endpoint must be specified") return nil, errors.New("endpoint must be specified")
} }
if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") { if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
// Backwards compatibility with geth < 1.5 which required // Backwards compatibility with geth < 1.5 which required
// these prefixes. // these prefixes.
endpoint = endpoint[4:] endpoint = endpoint[4:]
} }
var opts []rpc.ClientOption var opts []rpc.ClientOption
if len(headers) > 0 { if len(headers) > 0 {
var customHeaders = make(http.Header) var customHeaders = make(http.Header)
for _, h := range headers { for _, h := range headers {
kv := strings.Split(h, ":") kv := strings.Split(h, ":")
if len(kv) != 2 { if len(kv) != 2 {
return nil, fmt.Errorf("invalid http header directive: %q", h) return nil, fmt.Errorf("invalid http header directive: %q", h)
} }
customHeaders.Add(kv[0], kv[1]) customHeaders.Add(kv[0], kv[1])
} }
opts = append(opts, rpc.WithHeaders(customHeaders)) opts = append(opts, rpc.WithHeaders(customHeaders))
} }
return rpc.DialOptions(context.Background(), endpoint, opts...) return rpc.DialOptions(context.Background(), endpoint, opts...)
} }
@ -2209,18 +2317,23 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
gspec = MakeGenesis(ctx) gspec = MakeGenesis(ctx)
chainDb = MakeChainDatabase(ctx, stack, readonly) chainDb = MakeChainDatabase(ctx, stack, readonly)
) )
config, _, err := core.SetupGenesisBlock(chainDb, trie.NewDatabase(chainDb), gspec) config, _, err := core.SetupGenesisBlock(chainDb, trie.NewDatabase(chainDb), gspec)
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec) cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec)
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
ethashConfig := ethconfig.Defaults.Ethash ethashConfig := ethconfig.Defaults.Ethash
if ctx.Bool(FakePoWFlag.Name) { if ctx.Bool(FakePoWFlag.Name) {
ethashConfig.PowMode = ethash.ModeFake ethashConfig.PowMode = ethash.ModeFake
} }
configs := &ethconfig.Config{ configs := &ethconfig.Config{
Genesis: gspec, Genesis: gspec,
HeimdallURL: ctx.String(HeimdallURLFlag.Name), HeimdallURL: ctx.String(HeimdallURLFlag.Name),
@ -2232,6 +2345,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
} }
_ = CreateBorEthereum(configs) _ = CreateBorEthereum(configs)
engine := ethconfig.CreateConsensusEngine(stack, config, configs, &ethashConfig, cliqueConfig, nil, false, chainDb, nil) engine := ethconfig.CreateConsensusEngine(stack, config, configs, &ethashConfig, cliqueConfig, nil, false, chainDb, nil)
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
@ -2248,6 +2362,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
cache.Preimages = true cache.Preimages = true
log.Info("Enabling recording of key preimages since archive mode is used") log.Info("Enabling recording of key preimages since archive mode is used")
} }
if !ctx.Bool(SnapshotFlag.Name) { if !ctx.Bool(SnapshotFlag.Name) {
cache.SnapshotLimit = 0 // Disabled cache.SnapshotLimit = 0 // Disabled
} }
@ -2259,9 +2374,11 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100 cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
} }
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100 cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
} }
vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)} vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}
// Disable transaction indexing/unindexing by default. // Disable transaction indexing/unindexing by default.

View file

@ -54,5 +54,6 @@ func showDeprecated(*cli.Context) error {
fmt.Println(flag.String()) fmt.Println(flag.String())
} }
fmt.Println() fmt.Println()
return nil return nil
} }

View file

@ -182,6 +182,7 @@ func (c *Console) initWeb3(bridge *bridge) error {
if err := c.jsre.Compile("bignumber.js", deps.BigNumberJS); err != nil { if err := c.jsre.Compile("bignumber.js", deps.BigNumberJS); err != nil {
return fmt.Errorf("bignumber.js: %v", err) return fmt.Errorf("bignumber.js: %v", err)
} }
if err := c.jsre.Compile("web3.js", deps.Web3JS); err != nil { if err := c.jsre.Compile("web3.js", deps.Web3JS); err != nil {
return fmt.Errorf("web3.js: %v", err) return fmt.Errorf("web3.js: %v", err)
} }
@ -208,6 +209,7 @@ func (c *Console) initExtensions() error {
if err != nil { if err != nil {
if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == methodNotFound { if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == methodNotFound {
log.Warn("Server does not support method rpc_modules, using default API list.") log.Warn("Server does not support method rpc_modules, using default API list.")
apis = defaultAPIs apis = defaultAPIs
} else { } else {
return err return err
@ -260,6 +262,7 @@ func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) {
if personal == nil || c.prompter == nil { if personal == nil || c.prompter == nil {
return return
} }
log.Warn("Enabling deprecated personal namespace") log.Warn("Enabling deprecated personal namespace")
jeth := vm.NewObject() jeth := vm.NewObject()
vm.Set("jeth", jeth) vm.Set("jeth", jeth)

View file

@ -173,6 +173,7 @@ func genUncles(i int, gen *BlockGen) {
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) { func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Create the database in memory or in a temporary directory. // Create the database in memory or in a temporary directory.
var db ethdb.Database var db ethdb.Database
var err error var err error
if !disk { if !disk {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
@ -264,6 +265,7 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
if n == 0 { if n == 0 {
rawdb.WriteChainConfig(db, hash, params.AllEthashProtocolChanges) rawdb.WriteChainConfig(db, hash, params.AllEthashProtocolChanges)
} }
rawdb.WriteHeadHeaderHash(db, hash) rawdb.WriteHeadHeaderHash(db, hash)
if full || n == 0 { if full || n == 0 {
@ -307,6 +309,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil { if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err) b.Fatalf("error opening database at %v: %v", dir, err)
} }
chain, err := NewBlockChain(db, &cacheConfig, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil) chain, err := NewBlockChain(db, &cacheConfig, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
b.Fatalf("error creating chain: %v", err) b.Fatalf("error creating chain: %v", err)

View file

@ -73,6 +73,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if block.Withdrawals() == nil { if block.Withdrawals() == nil {
return fmt.Errorf("missing withdrawals in block body") return fmt.Errorf("missing withdrawals in block body")
} }
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash { if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash) return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
} }

View file

@ -98,6 +98,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
addr = crypto.PubkeyToAddress(key.PublicKey) addr = crypto.PubkeyToAddress(key.PublicKey)
config = *params.AllCliqueProtocolChanges config = *params.AllCliqueProtocolChanges
) )
engine = beacon.New(clique.New(params.AllCliqueProtocolChanges.Clique, rawdb.NewMemoryDatabase())) engine = beacon.New(clique.New(params.AllCliqueProtocolChanges.Clique, rawdb.NewMemoryDatabase()))
gspec = &Genesis{ gspec = &Genesis{
Config: &config, Config: &config,
@ -112,6 +113,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
td := 0 td := 0
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
for i, block := range blocks { for i, block := range blocks {
header := block.Header() header := block.Header()
if i > 0 { if i > 0 {
@ -127,6 +129,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
// calculate td // calculate td
td += int(block.Difficulty().Uint64()) td += int(block.Difficulty().Uint64())
} }
preBlocks = blocks preBlocks = blocks
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, nil) postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, nil)
@ -221,6 +224,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
seals = append(seals, true) seals = append(seals, true)
} }
_, results := engine.VerifyHeaders(chain, headers, seals) _, results := engine.VerifyHeaders(chain, headers, seals)
for i := 0; i < len(headers); i++ { for i := 0; i < len(headers); i++ {
select { select {

View file

@ -274,11 +274,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr return nil, genesisErr
} }
log.Info("") log.Info("")
log.Info(strings.Repeat("-", 153)) log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.Description(), "\n") { for _, line := range strings.Split(chainConfig.Description(), "\n") {
log.Info(line) log.Info(line)
} }
log.Info(strings.Repeat("-", 153)) log.Info(strings.Repeat("-", 153))
log.Info("") log.Info("")
@ -381,6 +384,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
snapBlock := bc.CurrentSnapBlock() snapBlock := bc.CurrentSnapBlock()
if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 { if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 {
needRewind = true needRewind = true
if snapBlock.Number.Uint64() < low || low == 0 { if snapBlock.Number.Uint64() < low || low == 0 {
low = snapBlock.Number.Uint64() low = snapBlock.Number.Uint64()
} }
@ -426,6 +430,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer) log.Warn("Enabling snapshot recovery", "chainhead", head.Number, "diskbase", *layer)
recover = true recover = true
} }
snapconfig := snapshot.Config{ snapconfig := snapshot.Config{
CacheSize: bc.cacheConfig.SnapshotLimit, CacheSize: bc.cacheConfig.SnapshotLimit,
Recovery: recover, Recovery: recover,
@ -454,11 +459,13 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
// Rewind the chain in case of an incompatible config upgrade. // Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok { if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat) log.Warn("Rewinding chain to upgrade configuration", "err", compat)
if compat.RewindToTime > 0 { if compat.RewindToTime > 0 {
bc.SetHeadWithTimestamp(compat.RewindToTime) bc.SetHeadWithTimestamp(compat.RewindToTime)
} else { } else {
bc.SetHead(compat.RewindToBlock) bc.SetHead(compat.RewindToBlock)
} }
rawdb.WriteChainConfig(db, genesisHash, chainConfig) rawdb.WriteChainConfig(db, genesisHash, chainConfig)
} }
// Start tx indexer/unindexer if required. // Start tx indexer/unindexer if required.
@ -466,8 +473,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
bc.txLookupLimit = *txLookupLimit bc.txLookupLimit = *txLookupLimit
bc.wg.Add(1) bc.wg.Add(1)
go bc.maintainTxIndex() go bc.maintainTxIndex()
} }
return bc, nil return bc, nil
} }
@ -486,6 +495,7 @@ func NewParallelBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis
Preimages: cacheConfig.Preimages, Preimages: cacheConfig.Preimages,
}) })
chainConfig, _, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides) chainConfig, _, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides)
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr return nil, genesisErr
} }
@ -611,6 +621,7 @@ func (bc *BlockChain) loadLastState() error {
headHeader = header headHeader = header
} }
} }
bc.hc.SetCurrentHeader(headHeader) bc.hc.SetCurrentHeader(headHeader)
// Restore the last known head fast block // Restore the last known head fast block
@ -643,14 +654,18 @@ func (bc *BlockChain) loadLastState() error {
headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64()) headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64())
blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64()) blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64())
) )
if headHeader.Hash() != headBlock.Hash() { if headHeader.Hash() != headBlock.Hash() {
log.Info("Loaded most recent local header", "number", headHeader.Number, "hash", headHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.Time), 0))) log.Info("Loaded most recent local header", "number", headHeader.Number, "hash", headHeader.Hash(), "td", headerTd, "age", common.PrettyAge(time.Unix(int64(headHeader.Time), 0)))
} }
log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0))) log.Info("Loaded most recent local block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0)))
if headBlock.Hash() != currentSnapBlock.Hash() { if headBlock.Hash() != currentSnapBlock.Hash() {
fastTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64()) fastTd := bc.GetTd(currentSnapBlock.Hash(), currentSnapBlock.Number.Uint64())
log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0))) log.Info("Loaded most recent local snap block", "number", currentSnapBlock.Number, "hash", currentSnapBlock.Hash(), "td", fastTd, "age", common.PrettyAge(time.Unix(int64(currentSnapBlock.Time), 0)))
} }
if currentFinalBlock != nil { if currentFinalBlock != nil {
finalTd := bc.GetTd(currentFinalBlock.Hash(), currentFinalBlock.Number.Uint64()) finalTd := bc.GetTd(currentFinalBlock.Hash(), currentFinalBlock.Number.Uint64())
log.Info("Loaded most recent local finalized block", "number", currentFinalBlock.Number, "hash", currentFinalBlock.Hash(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalBlock.Time), 0))) log.Info("Loaded most recent local finalized block", "number", currentFinalBlock.Number, "hash", currentFinalBlock.Hash(), "td", finalTd, "age", common.PrettyAge(time.Unix(int64(currentFinalBlock.Time), 0)))
@ -671,6 +686,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
// Send chain head event to update the transaction pool // Send chain head event to update the transaction pool
header := bc.CurrentBlock() header := bc.CurrentBlock()
block := bc.GetBlock(header.Hash(), header.Number.Uint64()) block := bc.GetBlock(header.Hash(), header.Number.Uint64())
if block == nil { if block == nil {
// This should never happen. In practice, previsouly currentBlock // This should never happen. In practice, previsouly currentBlock
// contained the entire block whereas now only a "marker", so there // contained the entire block whereas now only a "marker", so there
@ -678,7 +694,9 @@ func (bc *BlockChain) SetHead(head uint64) error {
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4]) return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
} }
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
return nil return nil
} }
@ -693,6 +711,7 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
// Send chain head event to update the transaction pool // Send chain head event to update the transaction pool
header := bc.CurrentBlock() header := bc.CurrentBlock()
block := bc.GetBlock(header.Hash(), header.Number.Uint64()) block := bc.GetBlock(header.Hash(), header.Number.Uint64())
if block == nil { if block == nil {
// This should never happen. In practice, previsouly currentBlock // This should never happen. In practice, previsouly currentBlock
// contained the entire block whereas now only a "marker", so there // contained the entire block whereas now only a "marker", so there
@ -700,13 +719,16 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash()) log.Error("Current block not found in database", "block", header.Number, "hash", header.Hash())
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4]) return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
} }
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block}) bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
return nil return nil
} }
// SetFinalized sets the finalized block. // SetFinalized sets the finalized block.
func (bc *BlockChain) SetFinalized(header *types.Header) { func (bc *BlockChain) SetFinalized(header *types.Header) {
bc.currentFinalBlock.Store(header) bc.currentFinalBlock.Store(header)
if header != nil { if header != nil {
rawdb.WriteFinalizedBlockHash(bc.db, header.Hash()) rawdb.WriteFinalizedBlockHash(bc.db, header.Hash())
headFinalizedBlockGauge.Update(int64(header.Number.Uint64())) headFinalizedBlockGauge.Update(int64(header.Number.Uint64()))
@ -719,6 +741,7 @@ func (bc *BlockChain) SetFinalized(header *types.Header) {
// SetSafe sets the safe block. // SetSafe sets the safe block.
func (bc *BlockChain) SetSafe(header *types.Header) { func (bc *BlockChain) SetSafe(header *types.Header) {
bc.currentSafeBlock.Store(header) bc.currentSafeBlock.Store(header)
if header != nil { if header != nil {
headSafeBlockGauge.Update(int64(header.Number.Uint64())) headSafeBlockGauge.Update(int64(header.Number.Uint64()))
} else { } else {
@ -824,15 +847,17 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
if newHeadSnapBlock == nil { if newHeadSnapBlock == nil {
newHeadSnapBlock = bc.genesisBlock newHeadSnapBlock = bc.genesisBlock
} }
rawdb.WriteHeadFastBlockHash(db, newHeadSnapBlock.Hash()) rawdb.WriteHeadFastBlockHash(db, newHeadSnapBlock.Hash())
// Degrade the chain markers if they are explicitly reverted. // Degrade the chain markers if they are explicitly reverted.
// In theory we should update all in-memory markers in the // In theory, we should update all in-memory markers in the
// last step, however the direction of SetHead is from high // last step, however the direction of SetHead is from high
// to low, so it's safe the update in-memory markers directly. // to low, so it's safe the update in-memory markers directly.
bc.currentSnapBlock.Store(newHeadSnapBlock.Header()) bc.currentSnapBlock.Store(newHeadSnapBlock.Header())
headFastBlockGauge.Update(int64(newHeadSnapBlock.NumberU64())) headFastBlockGauge.Update(int64(newHeadSnapBlock.NumberU64()))
} }
var ( var (
headHeader = bc.CurrentBlock() headHeader = bc.CurrentBlock()
headNumber = headHeader.Number.Uint64() headNumber = headHeader.Number.Uint64()
@ -844,6 +869,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
if headNumber+1 < frozen { if headNumber+1 < frozen {
wipe = pivot == nil || headNumber >= *pivot wipe = pivot == nil || headNumber >= *pivot
} }
return headHeader, wipe // Only force wipe if full synced return headHeader, wipe // Only force wipe if full synced
} }
// Rewind the header chain, deleting all block bodies until then // Rewind the header chain, deleting all block bodies until then
@ -900,6 +926,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
log.Warn("SetHead invalidated safe block") log.Warn("SetHead invalidated safe block")
bc.SetSafe(nil) bc.SetSafe(nil)
} }
if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() { if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() {
log.Error("SetHead invalidated finalized block") log.Error("SetHead invalidated finalized block")
bc.SetFinalized(nil) bc.SetFinalized(nil)
@ -915,7 +942,9 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
if block == nil { if block == nil {
return fmt.Errorf("non existent block [%x..]", hash[:4]) return fmt.Errorf("non existent block [%x..]", hash[:4])
} }
root := block.Root() root := block.Root()
if !bc.HasState(root) { if !bc.HasState(root) {
return fmt.Errorf("non existent state [%x..]", root[:4]) return fmt.Errorf("non existent state [%x..]", root[:4])
} }
@ -923,6 +952,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
if !bc.chainmu.TryLock() { if !bc.chainmu.TryLock() {
return errChainStopped return errChainStopped
} }
bc.currentBlock.Store(block.Header()) bc.currentBlock.Store(block.Header())
headBlockGauge.Update(int64(block.NumberU64())) headBlockGauge.Update(int64(block.NumberU64()))
bc.chainmu.Unlock() bc.chainmu.Unlock()
@ -995,9 +1025,11 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
if block == nil { if block == nil {
return fmt.Errorf("export failed on #%d: not found", nr) return fmt.Errorf("export failed on #%d: not found", nr)
} }
if nr > first && block.ParentHash() != parentHash { if nr > first && block.ParentHash() != parentHash {
return fmt.Errorf("export failed: chain reorg during export") return fmt.Errorf("export failed: chain reorg during export")
} }
parentHash = block.Hash() parentHash = block.Hash()
if err := block.EncodeRLP(w); err != nil { if err := block.EncodeRLP(w); err != nil {
return err return err
@ -1094,6 +1126,7 @@ func (bc *BlockChain) Stop() {
recent := bc.GetBlockByNumber(number - offset) recent := bc.GetBlockByNumber(number - offset)
log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root()) log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
if err := triedb.Commit(recent.Root(), true); err != nil { if err := triedb.Commit(recent.Root(), true); err != nil {
log.Error("Failed to commit recent state trie", "err", err) log.Error("Failed to commit recent state trie", "err", err)
} }
@ -1101,6 +1134,7 @@ func (bc *BlockChain) Stop() {
} }
if snapBase != (common.Hash{}) { if snapBase != (common.Hash{}) {
log.Info("Writing snapshot state to disk", "root", snapBase) log.Info("Writing snapshot state to disk", "root", snapBase)
if err := triedb.Commit(snapBase, true); err != nil { if err := triedb.Commit(snapBase, true); err != nil {
log.Error("Failed to commit recent state trie", "err", err) log.Error("Failed to commit recent state trie", "err", err)
} }
@ -1450,6 +1484,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
if stats.ignored > 0 { if stats.ignored > 0 {
context = append(context, []interface{}{"ignored", stats.ignored}...) context = append(context, []interface{}{"ignored", stats.ignored}...)
} }
log.Debug("Imported new block receipts", context...) log.Debug("Imported new block receipts", context...)
return 0, nil return 0, nil
@ -1565,6 +1600,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
nodes, imgs = bc.triedb.Size() nodes, imgs = bc.triedb.Size()
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024 limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
) )
if nodes > limit || imgs > 4*1024*1024 { if nodes > limit || imgs > 4*1024*1024 {
bc.triedb.Cap(limit - ethdb.IdealBatchSize) bc.triedb.Cap(limit - ethdb.IdealBatchSize)
} }
@ -1597,6 +1633,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
bc.triegc.Push(root, number) bc.triegc.Push(root, number)
break break
} }
bc.triedb.Dereference(root) bc.triedb.Dereference(root)
} }
return stateSyncLogs, nil return stateSyncLogs, nil
@ -2026,6 +2063,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt)
blockPrefetchExecuteTimer.Update(time.Since(start)) blockPrefetchExecuteTimer.Update(time.Since(start))
if followupInterrupt.Load() { if followupInterrupt.Load() {
blockPrefetchInterruptMeter.Mark(1) blockPrefetchInterruptMeter.Mark(1)
} }
@ -2056,6 +2094,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
followupInterrupt.Store(true) followupInterrupt.Store(true)
return it.index, err return it.index, err
} }
vtime := time.Since(vstart) vtime := time.Since(vstart)
proctime := time.Since(start) // processing + validation proctime := time.Since(start) // processing + validation
@ -2086,6 +2125,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
} else { } else {
status, err = bc.writeBlockAndSetHead(context.Background(), block, receipts, logs, statedb, false) status, err = bc.writeBlockAndSetHead(context.Background(), block, receipts, logs, statedb, false)
} }
followupInterrupt.Store(true) followupInterrupt.Store(true)
if err != nil { if err != nil {
return it.index, err return it.index, err
@ -2353,6 +2393,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
return b.ParentHash(), err return b.ParentHash(), err
} }
} }
return block.Hash(), nil return block.Hash(), nil
} }
@ -2396,10 +2437,13 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
deletedTxs []common.Hash deletedTxs []common.Hash
addedTxs []common.Hash addedTxs []common.Hash
) )
oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64()) oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64())
if oldBlock == nil { if oldBlock == nil {
return errors.New("current head block missing") return errors.New("current head block missing")
} }
newBlock := newHead newBlock := newHead
// Reduce the longer chain to the same number as the shorter one // Reduce the longer chain to the same number as the shorter one
@ -2407,6 +2451,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
// Old chain is longer, gather all transactions and logs as deleted ones // Old chain is longer, gather all transactions and logs as deleted ones
for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) { for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) {
oldChain = append(oldChain, oldBlock) oldChain = append(oldChain, oldBlock)
for _, tx := range oldBlock.Transactions() { for _, tx := range oldBlock.Transactions() {
deletedTxs = append(deletedTxs, tx.Hash()) deletedTxs = append(deletedTxs, tx.Hash())
} }
@ -2433,6 +2478,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
} }
// Remove an old block as well as stash away a new block // Remove an old block as well as stash away a new block
oldChain = append(oldChain, oldBlock) oldChain = append(oldChain, oldBlock)
for _, tx := range oldBlock.Transactions() { for _, tx := range oldBlock.Transactions() {
deletedTxs = append(deletedTxs, tx.Hash()) deletedTxs = append(deletedTxs, tx.Hash())
} }
@ -2551,6 +2597,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
// Deleted logs + blocks: // Deleted logs + blocks:
var deletedLogs []*types.Log var deletedLogs []*types.Log
for i := len(oldChain) - 1; i >= 0; i-- { for i := len(oldChain) - 1; i >= 0; i-- {
// Also send event for blocks removed from the canon chain. // Also send event for blocks removed from the canon chain.
bc.chainSideFeed.Send(ChainSideEvent{Block: oldChain[i]}) bc.chainSideFeed.Send(ChainSideEvent{Block: oldChain[i]})
@ -2559,26 +2606,31 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
if logs := bc.collectLogs(oldChain[i], true); len(logs) > 0 { if logs := bc.collectLogs(oldChain[i], true); len(logs) > 0 {
deletedLogs = append(deletedLogs, logs...) deletedLogs = append(deletedLogs, logs...)
} }
if len(deletedLogs) > 512 { if len(deletedLogs) > 512 {
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs}) bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
deletedLogs = nil deletedLogs = nil
} }
} }
if len(deletedLogs) > 0 { if len(deletedLogs) > 0 {
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs}) bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
} }
// New logs: // New logs:
var rebirthLogs []*types.Log var rebirthLogs []*types.Log
for i := len(newChain) - 1; i >= 1; i-- { for i := len(newChain) - 1; i >= 1; i-- {
if logs := bc.collectLogs(newChain[i], false); len(logs) > 0 { if logs := bc.collectLogs(newChain[i], false); len(logs) > 0 {
rebirthLogs = append(rebirthLogs, logs...) rebirthLogs = append(rebirthLogs, logs...)
} }
if len(rebirthLogs) > 512 { if len(rebirthLogs) > 512 {
bc.logsFeed.Send(rebirthLogs) bc.logsFeed.Send(rebirthLogs)
rebirthLogs = nil rebirthLogs = nil
} }
} }
if len(rebirthLogs) > 0 { if len(rebirthLogs) > 0 {
bc.logsFeed.Send(rebirthLogs) bc.logsFeed.Send(rebirthLogs)
} }
@ -2652,6 +2704,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
if latestValidHash, err := bc.recoverAncestors(head); err != nil { if latestValidHash, err := bc.recoverAncestors(head); err != nil {
return latestValidHash, err return latestValidHash, err
} }
log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash()) log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash())
} }
// Run the reorg if necessary and set the given block as new head. // Run the reorg if necessary and set the given block as new head.
@ -2681,6 +2734,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...) context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
} }
log.Info("Chain head was updated", context...) log.Info("Chain head was updated", context...)
return head.Hash(), nil return head.Hash(), nil
} }
@ -2750,7 +2804,9 @@ func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{})
if bc.txLookupLimit != 0 && head >= bc.txLookupLimit { if bc.txLookupLimit != 0 && head >= bc.txLookupLimit {
from = head - bc.txLookupLimit + 1 from = head - bc.txLookupLimit + 1
} }
rawdb.IndexTransactions(bc.db, from, head+1, bc.quit) rawdb.IndexTransactions(bc.db, from, head+1, bc.quit)
return return
} }
// The tail flag is existent, but the whole chain is required to be indexed. // The tail flag is existent, but the whole chain is required to be indexed.
@ -2763,8 +2819,10 @@ func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{})
if end > head+1 { if end > head+1 {
end = head + 1 end = head + 1
} }
rawdb.IndexTransactions(bc.db, 0, end, bc.quit) rawdb.IndexTransactions(bc.db, 0, end, bc.quit)
} }
return return
} }
// Update the transaction index to the new chain state // Update the transaction index to the new chain state
@ -2835,11 +2893,14 @@ func summarizeBadBlock(block *types.Block, receipts []*types.Receipt, config *pa
i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(), i, receipt.CumulativeGasUsed, receipt.GasUsed, receipt.ContractAddress.Hex(),
receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState) receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState)
} }
version, vcs := version.Info() version, vcs := version.Info()
platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS) platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS)
if vcs != "" { if vcs != "" {
vcs = fmt.Sprintf("\nVCS: %s", vcs) vcs = fmt.Sprintf("\nVCS: %s", vcs)
} }
return fmt.Sprintf(` return fmt.Sprintf(`
########## BAD BLOCK ######### ########## BAD BLOCK #########
Block: %v (%#x) Block: %v (%#x)

View file

@ -138,6 +138,7 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
if bc.blockCache.Contains(hash) { if bc.blockCache.Contains(hash) {
return true return true
} }
if !bc.HasHeader(hash, number) { if !bc.HasHeader(hash, number) {
return false return false
} }

View file

@ -69,11 +69,13 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *G
// Full block-chain requested // Full block-chain requested
genDb, blocks := makeBlockChainWithGenesis(genesis, n, engine, canonicalSeed) genDb, blocks := makeBlockChainWithGenesis(genesis, n, engine, canonicalSeed)
_, err := blockchain.InsertChain(blocks) _, err := blockchain.InsertChain(blocks)
return genDb, genesis, blockchain, err return genDb, genesis, blockchain, err
} }
// Header-only chain requested // Header-only chain requested
genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed) genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed)
_, err := blockchain.InsertHeaderChain(headers, 1) _, err := blockchain.InsertHeaderChain(headers, 1)
return genDb, genesis, blockchain, err return genDb, genesis, blockchain, err
} }
@ -261,6 +263,7 @@ func testInsertAfterMerge(t *testing.T, blockchain *BlockChain, i, n int, full b
if _, err := blockchain2.InsertChain(blockChainB); err != nil { if _, err := blockchain2.InsertChain(blockChainB); err != nil {
t.Fatalf("failed to insert forking chain: %v", err) t.Fatalf("failed to insert forking chain: %v", err)
} }
if blockchain2.CurrentBlock().Number.Uint64() != blockChainB[len(blockChainB)-1].NumberU64() { if blockchain2.CurrentBlock().Number.Uint64() != blockChainB[len(blockChainB)-1].NumberU64() {
t.Fatalf("failed to reorg to the given chain") t.Fatalf("failed to reorg to the given chain")
} }
@ -767,6 +770,7 @@ func TestFastVsFullChains(t *testing.T) {
} }
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
) )
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, func(i int, block *BlockGen) { _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, func(i int, block *BlockGen) {
block.SetCoinbase(common.Address{0x00}) block.SetCoinbase(common.Address{0x00})
@ -902,6 +906,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
return db return db
} }
// Configure a subchain to roll back // Configure a subchain to roll back
@ -914,6 +919,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
if num := chain.CurrentBlock().Number.Uint64(); num != block { if num := chain.CurrentBlock().Number.Uint64(); num != block {
t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block) t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block)
} }
if num := chain.CurrentSnapBlock().Number.Uint64(); num != fast { if num := chain.CurrentSnapBlock().Number.Uint64(); num != fast {
t.Errorf("%s head snap-block mismatch: have #%v, want #%v", kind, num, fast) t.Errorf("%s head snap-block mismatch: have #%v, want #%v", kind, num, fast)
} }
@ -1122,6 +1128,7 @@ func TestLogReorgs(t *testing.T) {
rmLogsCh := make(chan RemovedLogsEvent) rmLogsCh := make(chan RemovedLogsEvent)
blockchain.SubscribeRemovedLogsEvent(rmLogsCh) blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) { _, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) {
if i == 1 { if i == 1 {
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, code), signer, key1) tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, gen.header.BaseFee, code), signer, key1)
@ -1198,6 +1205,7 @@ func TestLogRebirth(t *testing.T) {
if _, err := blockchain.InsertChain(chain); err != nil { if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err) t.Fatalf("failed to insert chain: %v", err)
} }
checkLogEvents(t, newLogCh, rmLogsCh, 10, 0) checkLogEvents(t, newLogCh, rmLogsCh, 10, 0)
// Generate long reorg chain containing more logs. Inserting the // Generate long reorg chain containing more logs. Inserting the
@ -1224,6 +1232,7 @@ func TestLogRebirth(t *testing.T) {
if _, err := blockchain.InsertChain(forkChain); err != nil { if _, err := blockchain.InsertChain(forkChain); err != nil {
t.Fatalf("failed to insert forked chain: %v", err) t.Fatalf("failed to insert forked chain: %v", err)
} }
checkLogEvents(t, newLogCh, rmLogsCh, 10, 10) checkLogEvents(t, newLogCh, rmLogsCh, 10, 10)
// This chain segment is rooted in the original chain, but doesn't contain any logs. // This chain segment is rooted in the original chain, but doesn't contain any logs.
@ -1233,6 +1242,7 @@ func TestLogRebirth(t *testing.T) {
if _, err := blockchain.InsertChain(newBlocks); err != nil { if _, err := blockchain.InsertChain(newBlocks); err != nil {
t.Fatalf("failed to insert forked chain: %v", err) t.Fatalf("failed to insert forked chain: %v", err)
} }
checkLogEvents(t, newLogCh, rmLogsCh, 10, 10) checkLogEvents(t, newLogCh, rmLogsCh, 10, 10)
} }
@ -1288,6 +1298,7 @@ func TestSideLogRebirth(t *testing.T) {
func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) { func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan RemovedLogsEvent, wantNew, wantRemoved int) {
t.Helper() t.Helper()
var ( var (
countNew int countNew int
countRm int countRm int
@ -1297,25 +1308,31 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
for len(logsCh) > 0 { for len(logsCh) > 0 {
x := <-logsCh x := <-logsCh
countNew += len(x) countNew += len(x)
for _, log := range x { for _, log := range x {
// We expect added logs to be in ascending order: 0:0, 0:1, 1:0 ... // We expect added logs to be in ascending order: 0:0, 0:1, 1:0 ...
have := 100*int(log.BlockNumber) + int(log.TxIndex) have := 100*int(log.BlockNumber) + int(log.TxIndex)
if have < prev { if have < prev {
t.Fatalf("Expected new logs to arrive in ascending order (%d < %d)", have, prev) t.Fatalf("Expected new logs to arrive in ascending order (%d < %d)", have, prev)
} }
prev = have prev = have
} }
} }
prev = 0 prev = 0
for len(rmLogsCh) > 0 { for len(rmLogsCh) > 0 {
x := <-rmLogsCh x := <-rmLogsCh
countRm += len(x.Logs) countRm += len(x.Logs)
for _, log := range x.Logs { for _, log := range x.Logs {
// We expect removed logs to be in ascending order: 0:0, 0:1, 1:0 ... // We expect removed logs to be in ascending order: 0:0, 0:1, 1:0 ...
have := 100*int(log.BlockNumber) + int(log.TxIndex) have := 100*int(log.BlockNumber) + int(log.TxIndex)
if have < prev { if have < prev {
t.Fatalf("Expected removed logs to arrive in ascending order (%d < %d)", have, prev) t.Fatalf("Expected removed logs to arrive in ascending order (%d < %d)", have, prev)
} }
prev = have prev = have
} }
} }
@ -1323,6 +1340,7 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
if countNew != wantNew { if countNew != wantNew {
t.Fatalf("wrong number of log events: got %d, want %d", countNew, wantNew) t.Fatalf("wrong number of log events: got %d, want %d", countNew, wantNew)
} }
if countRm != wantRemoved { if countRm != wantRemoved {
t.Fatalf("wrong number of removed log events: got %d, want %d", countRm, wantRemoved) t.Fatalf("wrong number of removed log events: got %d, want %d", countRm, wantRemoved)
} }
@ -1338,6 +1356,7 @@ func TestReorgSideEvent(t *testing.T) {
} }
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
) )
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil) blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
defer blockchain.Stop() defer blockchain.Stop()
@ -1471,6 +1490,7 @@ func TestEIP155Transition(t *testing.T) {
Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}}, Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
} }
) )
genDb, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, block *BlockGen) { genDb, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, block *BlockGen) {
var ( var (
tx *types.Transaction tx *types.Transaction
@ -1582,6 +1602,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
Alloc: GenesisAlloc{address: {Balance: funds}}, Alloc: GenesisAlloc{address: {Balance: funds}},
} }
) )
_, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, block *BlockGen) { _, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, block *BlockGen) {
var ( var (
tx *types.Transaction tx *types.Transaction
@ -1650,6 +1671,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
if i > 0 { if i > 0 {
parent = blocks[i-1] parent = blocks[i-1]
} }
fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
forks[i] = fork[0] forks[i] = fork[0]
} }
@ -1659,6 +1681,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
for i := 0; i < len(blocks); i++ { for i := 0; i < len(blocks); i++ {
@ -1695,6 +1718,7 @@ func TestTrieForkGC(t *testing.T) {
if i > 0 { if i > 0 {
parent = blocks[i-1] parent = blocks[i-1]
} }
fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
forks[i] = fork[0] forks[i] = fork[0]
} }
@ -1703,6 +1727,7 @@ func TestTrieForkGC(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
for i := 0; i < len(blocks); i++ { for i := 0; i < len(blocks); i++ {
@ -1741,6 +1766,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if _, err := chain.InsertChain(shared); err != nil { if _, err := chain.InsertChain(shared); err != nil {
@ -1814,9 +1840,11 @@ func TestBlockchainRecovery(t *testing.T) {
// Reopen broken blockchain again // Reopen broken blockchain again
ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil) ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
defer ancient.Stop() defer ancient.Stop()
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 { if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
t.Errorf("head block mismatch: have #%v, want #%v", num, 0) t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
} }
if num := ancient.CurrentSnapBlock().Number.Uint64(); num != midBlock.NumberU64() { if num := ancient.CurrentSnapBlock().Number.Uint64(); num != midBlock.NumberU64() {
t.Errorf("head snap-block mismatch: have #%v, want #%v", num, midBlock.NumberU64()) t.Errorf("head snap-block mismatch: have #%v, want #%v", num, midBlock.NumberU64())
} }
@ -1837,6 +1865,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
if _, err := tmpChain.InsertChain(sideblocks); err != nil { if _, err := tmpChain.InsertChain(sideblocks); err != nil {
t.Fatal("processing side chain failed:", err) t.Fatal("processing side chain failed:", err)
} }
t.Log("sidechain head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash()) t.Log("sidechain head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash())
sidechainReceipts := make([]types.Receipts, len(sideblocks)) sidechainReceipts := make([]types.Receipts, len(sideblocks))
for i, block := range sideblocks { for i, block := range sideblocks {
@ -1846,6 +1875,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
if _, err := tmpChain.InsertChain(canonblocks); err != nil { if _, err := tmpChain.InsertChain(canonblocks); err != nil {
t.Fatal("processing canon chain failed:", err) t.Fatal("processing canon chain failed:", err)
} }
t.Log("canon head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash()) t.Log("canon head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash())
canonReceipts := make([]types.Receipts, len(canonblocks)) canonReceipts := make([]types.Receipts, len(canonblocks))
for i, block := range canonblocks { for i, block := range canonblocks {
@ -1876,6 +1906,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
if err == nil { if err == nil {
t.Fatal("expected error from InsertReceiptChain.") t.Fatal("expected error from InsertReceiptChain.")
} }
if ancientChain.CurrentSnapBlock().Number.Uint64() != 0 { if ancientChain.CurrentSnapBlock().Number.Uint64() != 0 {
t.Fatalf("failed to rollback ancient data, want %d, have %d", 0, ancientChain.CurrentSnapBlock().Number) t.Fatalf("failed to rollback ancient data, want %d, have %d", 0, ancientChain.CurrentSnapBlock().Number)
} }
@ -1888,6 +1919,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("can't import canon chain receipts: %v", err) t.Fatalf("can't import canon chain receipts: %v", err)
} }
if ancientChain.CurrentSnapBlock().Number.Uint64() != canonblocks[len(canonblocks)-1].NumberU64() { if ancientChain.CurrentSnapBlock().Number.Uint64() != canonblocks[len(canonblocks)-1].NumberU64() {
t.Fatalf("failed to insert ancient recept chain after rollback") t.Fatalf("failed to insert ancient recept chain after rollback")
} }
@ -1922,6 +1954,7 @@ func TestLowDiffLongChain(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.stopWithoutSaving() defer chain.stopWithoutSaving()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -1984,6 +2017,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
// Activate the transition since genesis if required // Activate the transition since genesis if required
@ -1995,6 +2029,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
// Set the terminal total difficulty in the config // Set the terminal total difficulty in the config
gspec.Config.TerminalTotalDifficulty = big.NewInt(0) gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
} }
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) { genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) {
tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key) tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key)
if err != nil { if err != nil {
@ -2133,6 +2168,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
var ( var (
@ -2304,6 +2340,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
var ( var (
@ -2316,7 +2353,9 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
for _, block := range blocks { for _, block := range blocks {
headers = append(headers, block.Header()) headers = append(headers, block.Header())
} }
i, err := chain.InsertHeaderChain(headers, 1) i, err := chain.InsertHeaderChain(headers, 1)
if err != nil { if err != nil {
return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err) return fmt.Errorf("index %d, number %d: %w", i, headers[i].Number, err)
} }
@ -2425,6 +2464,7 @@ func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Gene
b.SetCoinbase(common.Address{2}) b.SetCoinbase(common.Address{2})
b.OffsetTime(-9) b.OffsetTime(-9)
}) })
var heavyChain []*types.Block var heavyChain []*types.Block
heavyChain = append(heavyChain, longChain[:parentIndex+1]...) heavyChain = append(heavyChain, longChain[:parentIndex+1]...)
heavyChain = append(heavyChain, heavyChainExt...) heavyChain = append(heavyChain, heavyChainExt...)
@ -2451,6 +2491,7 @@ func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Gene
if shorterNum >= longerNum { if shorterNum >= longerNum {
return nil, nil, nil, nil, fmt.Errorf("test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) return nil, nil, nil, nil, fmt.Errorf("test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum)
} }
return chain, longChain, heavyChain, genesis, nil return chain, longChain, heavyChain, genesis, nil
} }
@ -2464,11 +2505,13 @@ func TestReorgToShorterRemovesCanonMapping(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(canonblocks); err != nil { if n, err := chain.InsertChain(canonblocks); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err) t.Fatalf("block %d: failed to insert into chain: %v", n, err)
} }
canonNum := chain.CurrentBlock().Number.Uint64() canonNum := chain.CurrentBlock().Number.Uint64()
canonHash := chain.CurrentBlock().Hash() canonHash := chain.CurrentBlock().Hash()
_, err = chain.InsertChain(sideblocks) _, err = chain.InsertChain(sideblocks)
@ -2502,6 +2545,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer chain.Stop() defer chain.Stop()
// Convert into headers // Convert into headers
@ -2553,6 +2597,7 @@ func TestTransactionIndices(t *testing.T) {
} }
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
) )
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) { _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
if err != nil { if err != nil {
@ -2606,6 +2651,7 @@ func TestTransactionIndices(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{})) chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
var tail uint64 var tail uint64
@ -2624,16 +2670,20 @@ func TestTransactionIndices(t *testing.T) {
rawdb.WriteAncientBlocks(ancientDb, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), []types.Receipts{nil}, big.NewInt(0)) rawdb.WriteAncientBlocks(ancientDb, append([]*types.Block{gspec.ToBlock()}, blocks...), append([]types.Receipts{{}}, receipts...), []types.Receipts{nil}, big.NewInt(0))
limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */} limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */}
for _, l := range limit { for _, l := range limit {
l := l l := l
chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil) chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
var tail uint64 var tail uint64
if l != 0 { if l != 0 {
tail = uint64(128) - l + 1 tail = uint64(128) - l + 1
} }
chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{})) chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
check(&tail, chain) check(&tail, chain)
chain.Stop() chain.Stop()
@ -2649,6 +2699,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}} gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
) )
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) { _, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 128, func(i int, block *BlockGen) {
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key) tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
if err != nil { if err != nil {
@ -2703,6 +2754,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
@ -2769,7 +2821,9 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
b.Fatalf("failed to insert shared chain: %v", err) b.Fatalf("failed to insert shared chain: %v", err)
} }
b.StopTimer() b.StopTimer()
block := chain.GetBlockByHash(chain.CurrentBlock().Hash()) block := chain.GetBlockByHash(chain.CurrentBlock().Hash())
if got := block.Transactions().Len(); got != numTxs*numBlocks { if got := block.Transactions().Len(); got != numTxs*numBlocks {
b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got)
} }
@ -2846,6 +2900,7 @@ func TestSideImportPrunedBlocks(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -2937,6 +2992,7 @@ func TestDeleteCreateRevert(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -3047,6 +3103,7 @@ func TestDeleteRecreateSlots(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -3124,6 +3181,7 @@ func TestDeleteRecreateAccount(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -3295,6 +3353,7 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
var asHash = func(num int) common.Hash { var asHash = func(num int) common.Hash {
@ -3426,6 +3485,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
statedb, _ := chain.State() statedb, _ := chain.State()
@ -3508,6 +3568,7 @@ func TestEIP2718Transition(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -3596,6 +3657,7 @@ func TestEIP1559Transition(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
@ -3674,8 +3736,7 @@ func TestEIP1559Transition(t *testing.T) {
// Tests the scenario the chain is requested to another point with the missing state. // Tests the scenario the chain is requested to another point with the missing state.
// It expects the state is recovered and all relevant chain markers are set correctly. // It expects the state is recovered and all relevant chain markers are set correctly.
func TestSetCanonical(t *testing.T) { func TestSetCanonical(t *testing.T) {
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) t.Parallel()
var ( var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey) address = crypto.PubkeyToAddress(key.PublicKey)
@ -3688,6 +3749,9 @@ func TestSetCanonical(t *testing.T) {
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker() engine = ethash.NewFaker()
) )
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
// Generate and import the canonical chain // Generate and import the canonical chain
_, canon, _ := GenerateChainWithGenesis(gspec, engine, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) { _, canon, _ := GenerateChainWithGenesis(gspec, engine, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) {
tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key) tx, err := types.SignTx(types.NewTransaction(gen.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, gen.header.BaseFee, nil), signer, key)
@ -3696,10 +3760,12 @@ func TestSetCanonical(t *testing.T) {
} }
gen.AddTx(tx) gen.AddTx(tx)
}) })
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil, nil) chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if n, err := chain.InsertChain(canon); err != nil { if n, err := chain.InsertChain(canon); err != nil {
@ -3714,12 +3780,14 @@ func TestSetCanonical(t *testing.T) {
} }
gen.AddTx(tx) gen.AddTx(tx)
}) })
for _, block := range side { for _, block := range side {
err := chain.InsertBlockWithoutSetHead(block) err := chain.InsertBlockWithoutSetHead(block)
if err != nil { if err != nil {
t.Fatalf("Failed to insert into chain: %v", err) t.Fatalf("Failed to insert into chain: %v", err)
} }
} }
for _, block := range side { for _, block := range side {
got := chain.GetBlockByHash(block.Hash()) got := chain.GetBlockByHash(block.Hash())
if got == nil { if got == nil {
@ -3732,12 +3800,15 @@ func TestSetCanonical(t *testing.T) {
if chain.CurrentBlock().Hash() != head.Hash() { if chain.CurrentBlock().Hash() != head.Hash() {
t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash()) t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash())
} }
if chain.CurrentSnapBlock().Hash() != head.Hash() { if chain.CurrentSnapBlock().Hash() != head.Hash() {
t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash()) t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash())
} }
if chain.CurrentHeader().Hash() != head.Hash() { if chain.CurrentHeader().Hash() != head.Hash() {
t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash()) t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash())
} }
if !chain.HasState(head.Root()) { if !chain.HasState(head.Root()) {
t.Fatalf("Lost block state %v %x", head.Number(), head.Hash()) t.Fatalf("Lost block state %v %x", head.Number(), head.Hash())
} }
@ -3787,6 +3858,7 @@ func TestCanonicalHashMarker(t *testing.T) {
// markers [1, 11] should be updated // markers [1, 11] should be updated
{10, 11}, {10, 11},
} }
for _, c := range cases { for _, c := range cases {
var ( var (
gspec = &Genesis{ gspec = &Genesis{
@ -3796,6 +3868,7 @@ func TestCanonicalHashMarker(t *testing.T) {
} }
engine = ethash.NewFaker() engine = ethash.NewFaker()
) )
_, forkA, _ := GenerateChainWithGenesis(gspec, engine, c.forkA, func(i int, gen *BlockGen) {}) _, forkA, _ := GenerateChainWithGenesis(gspec, engine, c.forkA, func(i int, gen *BlockGen) {})
_, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {}) _, forkB, _ := GenerateChainWithGenesis(gspec, engine, c.forkB, func(i int, gen *BlockGen) {})
@ -3804,10 +3877,12 @@ func TestCanonicalHashMarker(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
// Insert forkA and forkB, the canonical should on forkA still // Insert forkA and forkB, the canonical should on forkA still
if n, err := chain.InsertChain(forkA); err != nil { if n, err := chain.InsertChain(forkA); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err) t.Fatalf("block %d: failed to insert into chain: %v", n, err)
} }
if n, err := chain.InsertChain(forkB); err != nil { if n, err := chain.InsertChain(forkB); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err) t.Fatalf("block %d: failed to insert into chain: %v", n, err)
} }
@ -3816,12 +3891,15 @@ func TestCanonicalHashMarker(t *testing.T) {
if chain.CurrentBlock().Hash() != head.Hash() { if chain.CurrentBlock().Hash() != head.Hash() {
t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash()) t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash())
} }
if chain.CurrentSnapBlock().Hash() != head.Hash() { if chain.CurrentSnapBlock().Hash() != head.Hash() {
t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash()) t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash())
} }
if chain.CurrentHeader().Hash() != head.Hash() { if chain.CurrentHeader().Hash() != head.Hash() {
t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash()) t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash())
} }
if !chain.HasState(head.Root()) { if !chain.HasState(head.Root()) {
t.Fatalf("Lost block state %v %x", head.Number(), head.Hash()) t.Fatalf("Lost block state %v %x", head.Number(), head.Hash())
} }
@ -3840,10 +3918,12 @@ func TestCanonicalHashMarker(t *testing.T) {
for i := 0; i < len(forkB); i++ { for i := 0; i < len(forkB); i++ {
block := forkB[i] block := forkB[i]
hash := chain.GetCanonicalHash(block.NumberU64()) hash := chain.GetCanonicalHash(block.NumberU64())
if hash != block.Hash() { if hash != block.Hash() {
t.Fatalf("Unexpected canonical hash %d", block.NumberU64()) t.Fatalf("Unexpected canonical hash %d", block.NumberU64())
} }
} }
if c.forkA > c.forkB { if c.forkA > c.forkB {
for i := uint64(c.forkB) + 1; i <= uint64(c.forkA); i++ { for i := uint64(c.forkB) + 1; i <= uint64(c.forkA); i++ {
hash := chain.GetCanonicalHash(i) hash := chain.GetCanonicalHash(i)
@ -3852,6 +3932,7 @@ func TestCanonicalHashMarker(t *testing.T) {
} }
} }
} }
chain.Stop() chain.Stop()
} }
} }
@ -3873,6 +3954,7 @@ func TestTxIndexer(t *testing.T) {
engine = ethash.NewFaker() engine = ethash.NewFaker()
nonce = uint64(0) nonce = uint64(0)
) )
_, blocks, receipts := GenerateChainWithGenesis(gspec, engine, 128, func(i int, gen *BlockGen) { _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, 128, func(i int, gen *BlockGen) {
tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey) tx, _ := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("0xdeadbeef"), big.NewInt(1000), params.TxGas, big.NewInt(10*params.InitialBaseFee), nil), types.HomesteadSigner{}, testBankKey)
gen.AddTx(tx) gen.AddTx(tx)
@ -3885,12 +3967,15 @@ func TestTxIndexer(t *testing.T) {
if number == 0 { if number == 0 {
return return
} }
block := blocks[number-1] block := blocks[number-1]
for _, tx := range block.Transactions() { for _, tx := range block.Transactions() {
lookup := rawdb.ReadTxLookupEntry(db, tx.Hash()) lookup := rawdb.ReadTxLookupEntry(db, tx.Hash())
if exist && lookup == nil { if exist && lookup == nil {
t.Fatalf("missing %d %x", number, tx.Hash().Hex()) t.Fatalf("missing %d %x", number, tx.Hash().Hex())
} }
if !exist && lookup != nil { if !exist && lookup != nil {
t.Fatalf("unexpected %d %x", number, tx.Hash().Hex()) t.Fatalf("unexpected %d %x", number, tx.Hash().Hex())
} }
@ -3907,12 +3992,15 @@ func TestTxIndexer(t *testing.T) {
if tail == nil { if tail == nil {
t.Fatal("Failed to write tx index tail") t.Fatal("Failed to write tx index tail")
} }
if *tail != expTail { if *tail != expTail {
t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail) t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail)
} }
if *tail != 0 { if *tail != 0 {
verifyRange(db, 0, *tail-1, false) verifyRange(db, 0, *tail-1, false)
} }
verifyRange(db, *tail, 128, true) verifyRange(db, *tail, 128, true)
} }
@ -4035,6 +4123,7 @@ func TestTxIndexer(t *testing.T) {
tailC: 65, tailC: 65,
}, },
} }
for _, c := range cases { for _, c := range cases {
frdir := t.TempDir() frdir := t.TempDir()
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false) db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
@ -4177,6 +4266,7 @@ func TestTransientStorageReset(t *testing.T) {
ExtraEips: []int{1153}, // Enable transient storage EIP ExtraEips: []int{1153}, // Enable transient storage EIP
} }
) )
code := append([]byte{ code := append([]byte{
// TLoad value with location 1 // TLoad value with location 1
byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1,
@ -4251,8 +4341,10 @@ func TestTransientStorageReset(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to load state %v", err) t.Fatalf("Failed to load state %v", err)
} }
loc := common.BytesToHash([]byte{1}) loc := common.BytesToHash([]byte{1})
slot := state.GetState(destAddress, loc) slot := state.GetState(destAddress, loc)
if slot != (common.Hash{}) { if slot != (common.Hash{}) {
t.Fatalf("Unexpected dirty storage slot") t.Fatalf("Unexpected dirty storage slot")
} }
@ -4335,9 +4427,11 @@ func TestEIP3651(t *testing.T) {
b.AddTx(tx) b.AddTx(tx)
}) })
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr)}, nil, nil, nil) chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr)}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
if n, err := chain.InsertChain(blocks); err != nil { if n, err := chain.InsertChain(blocks); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err) t.Fatalf("block %d: failed to insert into chain: %v", n, err)
} }
@ -4347,6 +4441,7 @@ func TestEIP3651(t *testing.T) {
// 1+2: Ensure EIP-1559 access lists are accounted for via gas usage. // 1+2: Ensure EIP-1559 access lists are accounted for via gas usage.
innerGas := vm.GasQuickStep*2 + params.ColdSloadCostEIP2929*2 innerGas := vm.GasQuickStep*2 + params.ColdSloadCostEIP2929*2
expectedGas := params.TxGas + 5*vm.GasFastestStep + vm.GasQuickStep + 100 + innerGas // 100 because 0xaaaa is in access list expectedGas := params.TxGas + 5*vm.GasFastestStep + vm.GasQuickStep + 100 + innerGas // 100 because 0xaaaa is in access list
if block.GasUsed() != expectedGas { if block.GasUsed() != expectedGas {
t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed()) t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed())
} }
@ -4356,6 +4451,7 @@ func TestEIP3651(t *testing.T) {
// 3: Ensure that miner received only the tx's tip. // 3: Ensure that miner received only the tx's tip.
actual := state.GetBalance(block.Coinbase()) actual := state.GetBalance(block.Coinbase())
expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64()) expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
if actual.Cmp(expected) != 0 { if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual) t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
} }
@ -4363,6 +4459,7 @@ func TestEIP3651(t *testing.T) {
// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee). // 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
actual = new(big.Int).Sub(funds, state.GetBalance(addr1)) actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64())) expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 { if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual) t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
} }

View file

@ -99,11 +99,14 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
if b.gasPool == nil { if b.gasPool == nil {
b.SetCoinbase(common.Address{}) b.SetCoinbase(common.Address{})
} }
b.statedb.SetTxContext(tx.Hash(), len(b.txs)) b.statedb.SetTxContext(tx.Hash(), len(b.txs))
receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, nil) receipt, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, vmConfig, nil)
if err != nil { if err != nil {
panic(err) panic(err)
} }
b.txs = append(b.txs, tx) b.txs = append(b.txs, tx)
b.receipts = append(b.receipts, receipt) b.receipts = append(b.receipts, receipt)
} }
@ -226,6 +229,7 @@ func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) uint64 {
cpy := *w cpy := *w
cpy.Index = b.nextWithdrawalIndex() cpy.Index = b.nextWithdrawalIndex()
b.withdrawals = append(b.withdrawals, &cpy) b.withdrawals = append(b.withdrawals, &cpy)
return cpy.Index return cpy.Index
} }
@ -234,10 +238,12 @@ func (b *BlockGen) nextWithdrawalIndex() uint64 {
if len(b.withdrawals) != 0 { if len(b.withdrawals) != 0 {
return b.withdrawals[len(b.withdrawals)-1].Index + 1 return b.withdrawals[len(b.withdrawals)-1].Index + 1
} }
for i := b.i - 1; i >= 0; i-- { for i := b.i - 1; i >= 0; i-- {
if wd := b.chain[i].Withdrawals(); len(wd) != 0 { if wd := b.chain[i].Withdrawals(); len(wd) != 0 {
return wd[len(wd)-1].Index + 1 return wd[len(wd)-1].Index + 1
} }
if i == 0 { if i == 0 {
// Correctly set the index if no parent had withdrawals. // Correctly set the index if no parent had withdrawals.
if wd := b.parent.Withdrawals(); len(wd) != 0 { if wd := b.parent.Withdrawals(); len(wd) != 0 {
@ -245,6 +251,7 @@ func (b *BlockGen) nextWithdrawalIndex() uint64 {
} }
} }
} }
return 0 return 0
} }
@ -334,6 +341,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
if err != nil { if err != nil {
panic(fmt.Sprintf("state write error: %v", err)) panic(fmt.Sprintf("state write error: %v", err))
} }
if err := statedb.Database().TrieDB().Commit(root, false); err != nil { if err := statedb.Database().TrieDB().Commit(root, false); err != nil {
panic(fmt.Sprintf("trie write error: %v", err)) panic(fmt.Sprintf("trie write error: %v", err))
} }
@ -360,10 +368,13 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) { func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
_, err := genesis.Commit(db, trie.NewDatabase(db)) _, err := genesis.Commit(db, trie.NewDatabase(db))
if err != nil { if err != nil {
panic(err) panic(err)
} }
blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen) blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen)
return db, blocks, receipts return db, blocks, receipts
} }
@ -412,9 +423,11 @@ func makeHeaderChain(chainConfig *params.ChainConfig, parent *types.Header, n in
func makeHeaderChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Header) { func makeHeaderChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine, seed int) (ethdb.Database, []*types.Header) {
db, blocks := makeBlockChainWithGenesis(genesis, n, engine, seed) db, blocks := makeBlockChainWithGenesis(genesis, n, engine, seed)
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
for i, block := range blocks { for i, block := range blocks {
headers[i] = block.Header() headers[i] = block.Header()
} }
return db, headers return db, headers
} }
@ -423,6 +436,7 @@ func makeBlockChain(chainConfig *params.ChainConfig, parent *types.Block, n int,
blocks, _ := GenerateChain(chainConfig, parent, engine, db, n, func(i int, b *BlockGen) { blocks, _ := GenerateChain(chainConfig, parent, engine, db, n, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
}) })
return blocks return blocks
} }
@ -431,6 +445,7 @@ func makeBlockChainWithGenesis(genesis *Genesis, n int, engine consensus.Engine,
db, blocks, _ := GenerateChainWithGenesis(genesis, engine, n, func(i int, b *BlockGen) { db, blocks, _ := GenerateChainWithGenesis(genesis, engine, n, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)}) b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
}) })
return db, blocks return db, blocks
} }

View file

@ -122,18 +122,22 @@ func TestGenerateWithdrawalChain(t *testing.T) {
withdrawalIndex uint64 withdrawalIndex uint64
head = blockchain.CurrentBlock().Number.Uint64() head = blockchain.CurrentBlock().Number.Uint64()
) )
for i := 0; i < int(head); i++ { for i := 0; i < int(head); i++ {
block := blockchain.GetBlockByNumber(uint64(i)) block := blockchain.GetBlockByNumber(uint64(i))
if block == nil { if block == nil {
t.Fatalf("block %d not found", i) t.Fatalf("block %d not found", i)
} }
if len(block.Withdrawals()) == 0 { if len(block.Withdrawals()) == 0 {
continue continue
} }
for j := 0; j < len(block.Withdrawals()); j++ { for j := 0; j < len(block.Withdrawals()); j++ {
if block.Withdrawals()[j].Index != withdrawalIndex { if block.Withdrawals()[j].Index != withdrawalIndex {
t.Fatalf("withdrawal index %d does not equal expected index %d", block.Withdrawals()[j].Index, withdrawalIndex) t.Fatalf("withdrawal index %d does not equal expected index %d", block.Withdrawals()[j].Index, withdrawalIndex)
} }
withdrawalIndex += 1 withdrawalIndex += 1
} }
} }

View file

@ -83,10 +83,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err) t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
} }
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err) t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
} }
bc.Stop() bc.Stop()
blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err == nil { if _, err := conBc.InsertChain(blocks); err == nil {
t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0]) t.Fatalf("contra-fork chain accepted pro-fork block: %v", blocks[0])
@ -106,10 +109,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err) t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
} }
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err) t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
} }
bc.Stop() bc.Stop()
blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err == nil { if _, err := proBc.InsertChain(blocks); err == nil {
t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0]) t.Fatalf("pro-fork chain accepted contra-fork block: %v", blocks[0])
@ -131,9 +137,11 @@ func TestDAOForkRangeExtradata(t *testing.T) {
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import contra-fork chain for expansion: %v", err) t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
} }
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit contra-fork head for expansion: %v", err) t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
} }
blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
if _, err := conBc.InsertChain(blocks); err != nil { if _, err := conBc.InsertChain(blocks); err != nil {
t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err) t.Fatalf("contra-fork chain didn't accept pro-fork block post-fork: %v", err)
@ -143,15 +151,19 @@ func TestDAOForkRangeExtradata(t *testing.T) {
defer bc.Stop() defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
for j := 0; j < len(blocks)/2; j++ { for j := 0; j < len(blocks)/2; j++ {
blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j] blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
} }
if _, err := bc.InsertChain(blocks); err != nil { if _, err := bc.InsertChain(blocks); err != nil {
t.Fatalf("failed to import pro-fork chain for expansion: %v", err) t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
} }
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil { if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
t.Fatalf("failed to commit pro-fork head for expansion: %v", err) t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
} }
blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {}) blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
if _, err := proBc.InsertChain(blocks); err != nil { if _, err := proBc.InsertChain(blocks); err != nil {
t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err) t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err)

View file

@ -103,6 +103,7 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, extern *types.Header) (b
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
reorg := false reorg := false
externNum, localNum := extern.Number.Uint64(), current.Number.Uint64() externNum, localNum := extern.Number.Uint64(), current.Number.Uint64()
if externNum < localNum { if externNum < localNum {
reorg = true reorg = true
} else if externNum == localNum { } else if externNum == localNum {

View file

@ -71,27 +71,37 @@ type Genesis struct {
func ReadGenesis(db ethdb.Database) (*Genesis, error) { func ReadGenesis(db ethdb.Database) (*Genesis, error) {
var genesis Genesis var genesis Genesis
stored := rawdb.ReadCanonicalHash(db, 0) stored := rawdb.ReadCanonicalHash(db, 0)
if (stored == common.Hash{}) { if (stored == common.Hash{}) {
return nil, fmt.Errorf("invalid genesis hash in database: %x", stored) return nil, fmt.Errorf("invalid genesis hash in database: %x", stored)
} }
blob := rawdb.ReadGenesisStateSpec(db, stored) blob := rawdb.ReadGenesisStateSpec(db, stored)
if blob == nil { if blob == nil {
return nil, fmt.Errorf("genesis state missing from db") return nil, fmt.Errorf("genesis state missing from db")
} }
if len(blob) != 0 { if len(blob) != 0 {
if err := genesis.Alloc.UnmarshalJSON(blob); err != nil { if err := genesis.Alloc.UnmarshalJSON(blob); err != nil {
return nil, fmt.Errorf("could not unmarshal genesis state json: %s", err) return nil, fmt.Errorf("could not unmarshal genesis state json: %s", err)
} }
} }
genesis.Config = rawdb.ReadChainConfig(db, stored) genesis.Config = rawdb.ReadChainConfig(db, stored)
if genesis.Config == nil { if genesis.Config == nil {
return nil, fmt.Errorf("genesis config missing from db") return nil, fmt.Errorf("genesis config missing from db")
} }
genesisBlock := rawdb.ReadBlock(db, stored, 0) genesisBlock := rawdb.ReadBlock(db, stored, 0)
if genesisBlock == nil { if genesisBlock == nil {
return nil, fmt.Errorf("genesis block missing from db") return nil, fmt.Errorf("genesis block missing from db")
} }
genesisHeader := genesisBlock.Header() genesisHeader := genesisBlock.Header()
genesis.Nonce = genesisHeader.Nonce.Uint64() genesis.Nonce = genesisHeader.Nonce.Uint64()
genesis.Timestamp = genesisHeader.Time genesis.Timestamp = genesisHeader.Time
@ -136,6 +146,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
statedb.SetState(addr, key, value) statedb.SetState(addr, key, value)
} }
} }
return statedb.Commit(false) return statedb.Commit(false)
} }
@ -147,14 +158,17 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
if err != nil { if err != nil {
return err return err
} }
for addr, account := range *ga { for addr, account := range *ga {
statedb.AddBalance(addr, account.Balance) statedb.AddBalance(addr, account.Balance)
statedb.SetCode(addr, account.Code) statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce) statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage { for key, value := range account.Storage {
statedb.SetState(addr, key, value) statedb.SetState(addr, key, value)
} }
} }
root, err := statedb.Commit(false) root, err := statedb.Commit(false)
if err != nil { if err != nil {
return err return err
@ -170,6 +184,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
if err != nil { if err != nil {
return err return err
} }
rawdb.WriteGenesisStateSpec(db, blockhash, blob) rawdb.WriteGenesisStateSpec(db, blockhash, blob)
return nil return nil
} }
@ -178,6 +193,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
// hash and commits it into the provided trie database. // hash and commits it into the provided trie database.
func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error { func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
var alloc GenesisAlloc var alloc GenesisAlloc
blob := rawdb.ReadGenesisStateSpec(db, blockhash) blob := rawdb.ReadGenesisStateSpec(db, blockhash)
if len(blob) != 0 { if len(blob) != 0 {
if err := alloc.UnmarshalJSON(blob); err != nil { if err := alloc.UnmarshalJSON(blob); err != nil {
@ -206,6 +222,7 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash comm
return errors.New("not found") return errors.New("not found")
} }
} }
return alloc.flush(db, triedb, blockhash) return alloc.flush(db, triedb, blockhash)
} }
@ -295,6 +312,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
if genesis != nil && genesis.Config == nil { if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
} }
applyOverrides := func(config *params.ChainConfig) { applyOverrides := func(config *params.ChainConfig) {
if config != nil { if config != nil {
// TODO marcello double check // TODO marcello double check
@ -312,10 +330,12 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
} else { } else {
log.Info("Writing custom genesis block") log.Info("Writing custom genesis block")
} }
block, err := genesis.Commit(db, triedb) block, err := genesis.Commit(db, triedb)
if err != nil { if err != nil {
return genesis.Config, common.Hash{}, err return genesis.Config, common.Hash{}, err
} }
applyOverrides(genesis.Config) applyOverrides(genesis.Config)
return genesis.Config, block.Hash(), nil return genesis.Config, block.Hash(), nil
} }
@ -331,10 +351,12 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
if hash != stored { if hash != stored {
return genesis.Config, hash, &GenesisMismatchError{stored, hash} return genesis.Config, hash, &GenesisMismatchError{stored, hash}
} }
block, err := genesis.Commit(db, triedb) block, err := genesis.Commit(db, triedb)
if err != nil { if err != nil {
return genesis.Config, hash, err return genesis.Config, hash, err
} }
applyOverrides(genesis.Config) applyOverrides(genesis.Config)
return genesis.Config, block.Hash(), nil return genesis.Config, block.Hash(), nil
} }
@ -357,6 +379,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
rawdb.WriteChainConfig(db, stored, newcfg) rawdb.WriteChainConfig(db, stored, newcfg)
return newcfg, stored, nil return newcfg, stored, nil
} }
// nolint:errchkjson
storedData, _ := json.Marshal(storedcfg) storedData, _ := json.Marshal(storedcfg)
// Special case: if a private network is being used (no genesis and also no // Special case: if a private network is being used (no genesis and also no
// mainnet hash in the database), we must not apply the `configOrDefault` // mainnet hash in the database), we must not apply the `configOrDefault`
@ -373,7 +397,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
if head == nil { if head == nil {
return newcfg, stored, fmt.Errorf("missing head header") return newcfg, stored, fmt.Errorf("missing head header")
} }
compatErr := storedcfg.CheckCompatible(newcfg, head.Number.Uint64(), head.Time) compatErr := storedcfg.CheckCompatible(newcfg, head.Number.Uint64(), head.Time)
if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) { if compatErr != nil && ((head.Number.Uint64() != 0 && compatErr.RewindToBlock != 0) || (head.Time != 0 && compatErr.RewindToTime != 0)) {
return newcfg, stored, compatErr return newcfg, stored, compatErr
} }
@ -413,6 +439,7 @@ func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig
if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored { if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored {
return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()} return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()}
} }
return genesis.Config.Clique, nil return genesis.Config.Clique, nil
} }
// There is no stored chain config and no new config provided, // There is no stored chain config and no new config provided,
@ -478,11 +505,14 @@ func (g *Genesis) ToBlock() *types.Block {
head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee) head.BaseFee = new(big.Int).SetUint64(params.InitialBaseFee)
} }
} }
var withdrawals []*types.Withdrawal var withdrawals []*types.Withdrawal
if g.Config != nil && g.Config.IsShanghai(g.Timestamp) { if g.Config != nil && g.Config.IsShanghai(g.Timestamp) {
head.WithdrawalsHash = &types.EmptyWithdrawalsHash head.WithdrawalsHash = &types.EmptyWithdrawalsHash
withdrawals = make([]*types.Withdrawal, 0) withdrawals = make([]*types.Withdrawal, 0)
} }
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals) return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
} }
@ -500,6 +530,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block
if err := config.CheckConfigForkOrder(); err != nil { if err := config.CheckConfigForkOrder(); err != nil {
return nil, err return nil, err
} }
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength { if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength {
return nil, errors.New("can't start clique chain without signers") return nil, errors.New("can't start clique chain without signers")
} }

View file

@ -36,6 +36,7 @@ func TestInvalidCliqueConfig(t *testing.T) {
block := DefaultGoerliGenesisBlock() block := DefaultGoerliGenesisBlock()
block.ExtraData = []byte{} block.ExtraData = []byte{}
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
if _, err := block.Commit(db, trie.NewDatabase(db)); err == nil { if _, err := block.Commit(db, trie.NewDatabase(db)); err == nil {
t.Fatal("Expected error on invalid clique config") t.Fatal("Expected error on invalid clique config")
} }
@ -222,6 +223,8 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
} }
hash, _ = alloc.deriveHash() hash, _ = alloc.deriveHash()
) )
// nolint : errchkjson
blob, _ := json.Marshal(alloc) blob, _ := json.Marshal(alloc)
rawdb.WriteGenesisStateSpec(db, hash, blob) rawdb.WriteGenesisStateSpec(db, hash, blob)

View file

@ -400,6 +400,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time,
if res.ignored > 0 { if res.ignored > 0 {
context = append(context, []interface{}{"ignored", res.ignored}...) context = append(context, []interface{}{"ignored", res.ignored}...)
} }
log.Debug("Imported new block headers", context...) log.Debug("Imported new block headers", context...)
return res.status, err return res.status, err
} }
@ -531,6 +532,7 @@ func (hc *HeaderChain) GetHeadersFrom(number, count uint64) []rlp.RawValue {
if !ok { if !ok {
break break
} }
rlpData, _ := rlp.EncodeToBytes(header) rlpData, _ := rlp.EncodeToBytes(header)
headers = append(headers, rlpData) headers = append(headers, rlpData)
hash = header.ParentHash hash = header.ParentHash
@ -607,12 +609,15 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
batch = hc.chainDb.NewBatch() batch = hc.chainDb.NewBatch()
origin = true origin = true
) )
done := func(header *types.Header) bool { done := func(header *types.Header) bool {
if headTime > 0 { if headTime > 0 {
return header.Time <= headTime return header.Time <= headTime
} }
return header.Number.Uint64() <= headBlock return header.Number.Uint64() <= headBlock
} }
for hdr := hc.CurrentHeader(); hdr != nil && !done(hdr); hdr = hc.CurrentHeader() { for hdr := hc.CurrentHeader(); hdr != nil && !done(hdr); hdr = hc.CurrentHeader() {
num := hdr.Number.Uint64() num := hdr.Number.Uint64()

View file

@ -101,5 +101,6 @@ func (cacher *txSenderCacher) RecoverFromBlocks(signer types.Signer, blocks []*t
for _, block := range blocks { for _, block := range blocks {
txs = append(txs, block.Transactions()...) txs = append(txs, block.Transactions()...)
} }
cacher.Recover(signer, txs) cacher.Recover(signer, txs)
} }

View file

@ -68,6 +68,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
if err != nil { if err != nil {
return // Also invalid block, bail out return // Also invalid block, bail out
} }
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil { if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil {
return // Ugh, something went horribly wrong, bail out return // Ugh, something went horribly wrong, bail out

View file

@ -82,10 +82,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
default: default:
} }
} }
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number), header.BaseFee) msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number), header.BaseFee)
if err != nil { if err != nil {
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err) return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
} }
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, interruptCtx) receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, interruptCtx)
if err != nil { if err != nil {
@ -207,5 +209,6 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
// Create a new context to be used in the EVM environment // Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author) blockContext := NewEVMBlockContext(header, bc, author)
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, interruptCtx) return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, interruptCtx)
} }

View file

@ -80,6 +80,7 @@ func TestStateProcessorErrors(t *testing.T) {
}), signer, key1) }), signer, key1)
return tx return tx
} }
var mkDynamicCreationTx = func(nonce uint64, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, data []byte) *types.Transaction { var mkDynamicCreationTx = func(nonce uint64, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, data []byte) *types.Transaction {
tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{ tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
Nonce: nonce, Nonce: nonce,

View file

@ -77,6 +77,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
} else { } else {
gas = params.TxGas gas = params.TxGas
} }
dataLen := uint64(len(data)) dataLen := uint64(len(data))
// Bump the required gas by the amount of transactional data // Bump the required gas by the amount of transactional data
if dataLen > 0 { if dataLen > 0 {
@ -108,6 +109,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords { if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
return 0, ErrGasUintOverflow return 0, ErrGasUintOverflow
} }
gas += lenWords * params.InitCodeWordGas gas += lenWords * params.InitCodeWordGas
} }
} }
@ -165,8 +167,10 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
if baseFee != nil { if baseFee != nil {
msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), msg.GasFeeCap) msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), msg.GasFeeCap)
} }
var err error var err error
msg.From, err = types.Sender(s, tx) msg.From, err = types.Sender(s, tx)
return msg, err return msg, err
} }
@ -239,6 +243,7 @@ func (st *StateTransition) to() common.Address {
if st.msg == nil || st.msg.To == nil /* contract creation */ { if st.msg == nil || st.msg.To == nil /* contract creation */ {
return common.Address{} return common.Address{}
} }
return *st.msg.To return *st.msg.To
} }
@ -246,17 +251,21 @@ func (st *StateTransition) buyGas() error {
mgval := new(big.Int).SetUint64(st.msg.GasLimit) mgval := new(big.Int).SetUint64(st.msg.GasLimit)
mgval = mgval.Mul(mgval, st.msg.GasPrice) mgval = mgval.Mul(mgval, st.msg.GasPrice)
balanceCheck := mgval balanceCheck := mgval
if st.msg.GasFeeCap != nil { if st.msg.GasFeeCap != nil {
balanceCheck = new(big.Int).SetUint64(st.msg.GasLimit) balanceCheck = new(big.Int).SetUint64(st.msg.GasLimit)
balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap) balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap)
balanceCheck.Add(balanceCheck, st.msg.Value) balanceCheck.Add(balanceCheck, st.msg.Value)
} }
if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 { if have, want := st.state.GetBalance(st.msg.From), balanceCheck; have.Cmp(want) < 0 {
return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want) return fmt.Errorf("%w: address %v have %v want %v", ErrInsufficientFunds, st.msg.From.Hex(), have, want)
} }
if err := st.gp.SubGas(st.msg.GasLimit); err != nil { if err := st.gp.SubGas(st.msg.GasLimit); err != nil {
return err return err
} }
st.gasRemaining += st.msg.GasLimit st.gasRemaining += st.msg.GasLimit
st.initialGas = st.msg.GasLimit st.initialGas = st.msg.GasLimit
@ -296,10 +305,12 @@ func (st *StateTransition) preCheck() error {
return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh, return fmt.Errorf("%w: address %v, maxFeePerGas bit length: %d", ErrFeeCapVeryHigh,
msg.From.Hex(), l) msg.From.Hex(), l)
} }
if l := msg.GasTipCap.BitLen(); l > 256 { if l := msg.GasTipCap.BitLen(); l > 256 {
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh, return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh,
msg.From.Hex(), l) msg.From.Hex(), l)
} }
if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 { if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 {
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap, return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap,
msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap) msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap)
@ -327,7 +338,9 @@ func (st *StateTransition) preCheck() error {
// nil evm execution result. // nil evm execution result.
func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*ExecutionResult, error) { func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*ExecutionResult, error) {
input1 := st.state.GetBalance(st.msg.From) input1 := st.state.GetBalance(st.msg.From)
var input2 *big.Int var input2 *big.Int
if !st.noFeeBurnAndTip { if !st.noFeeBurnAndTip {
input2 = st.state.GetBalance(st.evm.Context.Coinbase) input2 = st.state.GetBalance(st.evm.Context.Coinbase)
} }
@ -348,6 +361,7 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
if tracer := st.evm.Config.Tracer; tracer != nil { if tracer := st.evm.Config.Tracer; tracer != nil {
tracer.CaptureTxStart(st.initialGas) tracer.CaptureTxStart(st.initialGas)
defer func() { defer func() {
tracer.CaptureTxEnd(st.gasRemaining) tracer.CaptureTxEnd(st.gasRemaining)
}() }()
@ -365,9 +379,11 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
if err != nil { if err != nil {
return nil, err return nil, err
} }
if st.gasRemaining < gas { if st.gasRemaining < gas {
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas) return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas)
} }
st.gasRemaining -= gas st.gasRemaining -= gas
// Check clause 6 // Check clause 6
@ -406,7 +422,9 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
// After EIP-3529: refunds are capped to gasUsed / 5 // After EIP-3529: refunds are capped to gasUsed / 5
st.refundGas(params.RefundQuotientEIP3529) st.refundGas(params.RefundQuotientEIP3529)
} }
effectiveTip := msg.GasPrice effectiveTip := msg.GasPrice
if rules.IsLondon { if rules.IsLondon {
effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee)) effectiveTip = cmath.BigMin(msg.GasTipCap, new(big.Int).Sub(msg.GasFeeCap, st.evm.Context.BaseFee))
} }
@ -430,12 +448,15 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
if rules.IsLondon { if rules.IsLondon {
burntContractAddress := common.HexToAddress(st.evm.ChainConfig().Bor.CalculateBurntContract(st.evm.Context.BlockNumber.Uint64())) burntContractAddress := common.HexToAddress(st.evm.ChainConfig().Bor.CalculateBurntContract(st.evm.Context.BlockNumber.Uint64()))
burnAmount := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.evm.Context.BaseFee) burnAmount := new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.evm.Context.BaseFee)
if !st.noFeeBurnAndTip { if !st.noFeeBurnAndTip {
st.state.AddBalance(burntContractAddress, burnAmount) st.state.AddBalance(burntContractAddress, burnAmount)
} }
} }
if !st.noFeeBurnAndTip { if !st.noFeeBurnAndTip {
st.state.AddBalance(st.evm.Context.Coinbase, amount) st.state.AddBalance(st.evm.Context.Coinbase, amount)
output1 := new(big.Int).SetBytes(input1.Bytes()) output1 := new(big.Int).SetBytes(input1.Bytes())
output2 := new(big.Int).SetBytes(input2.Bytes()) output2 := new(big.Int).SetBytes(input2.Bytes())
@ -472,6 +493,7 @@ func (st *StateTransition) refundGas(refundQuotient uint64) {
if refund > st.state.GetRefund() { if refund > st.state.GetRefund() {
refund = st.state.GetRefund() refund = st.state.GetRefund()
} }
st.gasRemaining += refund st.gasRemaining += refund
// Return ETH for remaining gas, exchanged at the original rate. // Return ETH for remaining gas, exchanged at the original rate.

View file

@ -1984,10 +1984,12 @@ func TestIssue23496(t *testing.T) {
SnapshotWait: true, SnapshotWait: true,
} }
) )
chain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil) chain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
_, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *core.BlockGen) { _, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0x02}) b.SetCoinbase(common.Address{0x02})
b.SetDifficulty(big.NewInt(1000000)) b.SetDifficulty(big.NewInt(1000000))
@ -1997,14 +1999,17 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[:1]); err != nil { if _, err := chain.InsertChain(blocks[:1]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err) t.Fatalf("Failed to import canonical chain start: %v", err)
} }
err = chain.StateCache().TrieDB().Commit(blocks[0].Root(), true) err = chain.StateCache().TrieDB().Commit(blocks[0].Root(), true)
if err != nil { if err != nil {
t.Fatal("on trieDB.Commit", err) t.Fatal("on trieDB.Commit", err)
} }
// Insert block B2 and commit the snapshot into disk // Insert block B2 and commit the snapshot into disk
if _, err := chain.InsertChain(blocks[1:2]); err != nil { if _, err := chain.InsertChain(blocks[1:2]); err != nil {
t.Fatalf("Failed to import canonical chain start: %v", err) t.Fatalf("Failed to import canonical chain start: %v", err)
} }
if err := chain.Snaps().Cap(blocks[1].Root(), 0); err != nil { if err := chain.Snaps().Cap(blocks[1].Root(), 0); err != nil {
t.Fatalf("Failed to flatten snapshots: %v", err) t.Fatalf("Failed to flatten snapshots: %v", err)
} }
@ -2035,20 +2040,24 @@ func TestIssue23496(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to reopen persistent database: %v", err) t.Fatalf("Failed to reopen persistent database: %v", err)
} }
defer db.Close() defer db.Close()
chain, err = core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil) chain, err = core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
} }
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4))
} }
if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(1) { if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(1) {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(1)) t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(1))
} }
@ -2057,12 +2066,15 @@ func TestIssue23496(t *testing.T) {
if _, err := chain.InsertChain(blocks[1:]); err != nil { if _, err := chain.InsertChain(blocks[1:]); err != nil {
t.Fatalf("Failed to import canonical chain tail: %v", err) t.Fatalf("Failed to import canonical chain tail: %v", err)
} }
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4) t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
} }
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentSnapBlock(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4)) t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, uint64(4))
} }
if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) { if head := chain.CurrentBlock(); head.Number.Uint64() != uint64(4) {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4)) t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4))
} }

View file

@ -1984,10 +1984,12 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256 config.SnapshotLimit = 256
config.SnapshotWait = true config.SnapshotWait = true
} }
chain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil) chain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
defer chain.Stop() defer chain.Stop()
// If sidechain blocks are needed, make a light chain and import it // If sidechain blocks are needed, make a light chain and import it
@ -2000,6 +2002,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
t.Fatalf("Failed to import side chain: %v", err) t.Fatalf("Failed to import side chain: %v", err)
} }
} }
canonblocks, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) { canonblocks, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) {
b.SetCoinbase(common.Address{0x02}) b.SetCoinbase(common.Address{0x02})
b.SetDifficulty(big.NewInt(1000000)) b.SetDifficulty(big.NewInt(1000000))
@ -2052,9 +2055,11 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader { if head := chain.CurrentHeader(); head.Number.Uint64() != tt.expHeadHeader {
t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader) t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader)
} }
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock { if head := chain.CurrentSnapBlock(); head.Number.Uint64() != tt.expHeadFastBlock {
t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock) t.Errorf("Head fast block mismatch: have %d, want %d", head.Number, tt.expHeadFastBlock)
} }
if head := chain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock { if head := chain.CurrentBlock(); head.Number.Uint64() != tt.expHeadBlock {
t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock) t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock)
} }

View file

@ -84,10 +84,12 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*core.BlockChain, []*type
// will happen during the block insertion. // will happen during the block insertion.
cacheConfig = core.DefaultCacheConfig cacheConfig = core.DefaultCacheConfig
) )
chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, nil, nil) chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
genDb, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, basic.chainBlocks, func(i int, b *core.BlockGen) {}) genDb, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, basic.chainBlocks, func(i int, b *core.BlockGen) {})
// Insert the blocks with configured settings. // Insert the blocks with configured settings.
@ -326,6 +328,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, SnapshotLimit: 0,
} }
newchain, err := core.NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil) newchain, err := core.NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
@ -401,6 +404,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
newBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *core.BlockGen) {}) newBlocks, _ := core.GenerateChain(params.TestChainConfig, blocks[len(blocks)-1], snaptest.engine, snaptest.genDb, snaptest.newBlocks, func(i int, b *core.BlockGen) {})
newchain.InsertChain(newBlocks) newchain.InsertChain(newBlocks)
newchain.Stop() newchain.Stop()
@ -422,6 +426,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
defer newchain.Stop() defer newchain.Stop()
snaptest.verify(t, newchain, blocks) snaptest.verify(t, newchain, blocks)
} }

View file

@ -4705,15 +4705,18 @@ func BenchmarkMultiAccountBatchInsert(b *testing.B) {
defer pool.Stop() defer pool.Stop()
b.ReportAllocs() b.ReportAllocs()
batches := make(types.Transactions, b.N) batches := make(types.Transactions, b.N)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
key, _ := crypto.GenerateKey() key, _ := crypto.GenerateKey()
account := crypto.PubkeyToAddress(key.PublicKey) account := crypto.PubkeyToAddress(key.PublicKey)
pool.currentState.AddBalance(account, big.NewInt(1000000)) pool.currentState.AddBalance(account, big.NewInt(1000000))
tx := transaction(uint64(0), 100000, key) tx := transaction(uint64(0), 100000, key)
batches[i] = tx batches[i] = tx
} }
// Benchmark importing the transactions into the queue // Benchmark importing the transactions into the queue
b.ResetTimer() b.ResetTimer()
for _, tx := range batches { for _, tx := range batches {
pool.AddRemotesSync([]*types.Transaction{tx}) pool.AddRemotesSync([]*types.Transaction{tx})
} }

View file

@ -508,6 +508,7 @@ func TestEip2929Cases(t *testing.T) {
ops := strings.Join(instrs, ", ") ops := strings.Join(instrs, ", ")
fmt.Printf("### Case %d\n\n", id) fmt.Printf("### Case %d\n\n", id)
id++ id++
fmt.Printf("%v\n\nBytecode: \n```\n%#x\n```\nOperations: \n```\n%v\n```\n\n", fmt.Printf("%v\n\nBytecode: \n```\n%#x\n```\nOperations: \n```\n%v\n```\n\n",
comment, comment,
code, ops) code, ops)

View file

@ -267,6 +267,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
_, stateDb := api.eth.miner.Pending() _, stateDb := api.eth.miner.Pending()
return stateDb.RawDump(opts), nil return stateDb.RawDump(opts), nil
} }
var header *types.Header var header *types.Header
if blockNr == rpc.LatestBlockNumber { if blockNr == rpc.LatestBlockNumber {
header = api.eth.blockchain.CurrentBlock() header = api.eth.blockchain.CurrentBlock()
@ -281,9 +282,11 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
} }
header = block.Header() header = block.Header()
} }
if header == nil { if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr) return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
} }
stateDb, err := api.eth.BlockChain().StateAt(header.Root) stateDb, err := api.eth.BlockChain().StateAt(header.Root)
if err != nil { if err != nil {
return state.Dump{}, err return state.Dump{}, err
@ -419,10 +422,13 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash,
if block == nil { if block == nil {
return StorageRangeResult{}, fmt.Errorf("block %#x not found", blockHash) return StorageRangeResult{}, fmt.Errorf("block %#x not found", blockHash)
} }
_, _, statedb, release, err := api.eth.stateAtTransaction(ctx, block, txIndex, 0) _, _, statedb, release, err := api.eth.stateAtTransaction(ctx, block, txIndex, 0)
if err != nil { if err != nil {
return StorageRangeResult{}, err return StorageRangeResult{}, err
} }
defer release() defer release()
st, err := statedb.StorageTrie(contractAddress) st, err := statedb.StorageTrie(contractAddress)
@ -523,6 +529,7 @@ func (api *DebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]c
if err != nil { if err != nil {
return nil, err return nil, err
} }
newTrie, err := trie.NewStateTrie(trie.StateTrieID(endBlock.Root()), triedb) newTrie, err := trie.NewStateTrie(trie.StateTrieID(endBlock.Root()), triedb)
if err != nil { if err != nil {
return nil, err return nil, err
@ -599,6 +606,7 @@ func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error
return uint64(i), nil return uint64(i), nil
} }
} }
return 0, errors.New("no state found") return 0, errors.New("no state found")
} }
@ -609,6 +617,8 @@ func (api *DebugAPI) SetTrieFlushInterval(interval string) error {
if err != nil { if err != nil {
return err return err
} }
api.eth.blockchain.SetTrieFlushInterval(t) api.eth.blockchain.SetTrieFlushInterval(t)
return nil return nil
} }

View file

@ -74,24 +74,32 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
if number == rpc.LatestBlockNumber { if number == rpc.LatestBlockNumber {
return b.eth.blockchain.CurrentBlock(), nil return b.eth.blockchain.CurrentBlock(), nil
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
if !b.eth.Merger().TDDReached() { if !b.eth.Merger().TDDReached() {
return nil, errors.New("'finalized' tag not supported on pre-merge network") return nil, errors.New("'finalized' tag not supported on pre-merge network")
} }
block := b.eth.blockchain.CurrentFinalBlock() block := b.eth.blockchain.CurrentFinalBlock()
if block != nil { if block != nil {
return block, nil return block, nil
} }
return nil, errors.New("finalized block not found") return nil, errors.New("finalized block not found")
} }
if number == rpc.SafeBlockNumber { if number == rpc.SafeBlockNumber {
if !b.eth.Merger().TDDReached() { if !b.eth.Merger().TDDReached() {
return nil, errors.New("'safe' tag not supported on pre-merge network") return nil, errors.New("'safe' tag not supported on pre-merge network")
} }
block := b.eth.blockchain.CurrentSafeBlock() block := b.eth.blockchain.CurrentSafeBlock()
if block != nil { if block != nil {
return block, nil return block, nil
} }
return nil, errors.New("safe block not found") return nil, errors.New("safe block not found")
} }
return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil
@ -129,18 +137,24 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
header := b.eth.blockchain.CurrentBlock() header := b.eth.blockchain.CurrentBlock()
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
} }
if number == rpc.FinalizedBlockNumber { if number == rpc.FinalizedBlockNumber {
if !b.eth.Merger().TDDReached() { if !b.eth.Merger().TDDReached() {
return nil, errors.New("'finalized' tag not supported on pre-merge network") return nil, errors.New("'finalized' tag not supported on pre-merge network")
} }
header := b.eth.blockchain.CurrentFinalBlock() header := b.eth.blockchain.CurrentFinalBlock()
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
} }
if number == rpc.SafeBlockNumber { if number == rpc.SafeBlockNumber {
if !b.eth.Merger().TDDReached() { if !b.eth.Merger().TDDReached() {
return nil, errors.New("'safe' tag not supported on pre-merge network") return nil, errors.New("'safe' tag not supported on pre-merge network")
} }
header := b.eth.blockchain.CurrentSafeBlock() header := b.eth.blockchain.CurrentSafeBlock()
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
} }
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
@ -155,9 +169,11 @@ func (b *EthAPIBackend) GetBody(ctx context.Context, hash common.Hash, number rp
if number < 0 || hash == (common.Hash{}) { if number < 0 || hash == (common.Hash{}) {
return nil, errors.New("invalid arguments; expect hash and no special block numbers") return nil, errors.New("invalid arguments; expect hash and no special block numbers")
} }
if body := b.eth.blockchain.GetBody(hash); body != nil { if body := b.eth.blockchain.GetBody(hash); body != nil {
return body, nil return body, nil
} }
return nil, errors.New("block body not found") return nil, errors.New("block body not found")
} }
@ -246,6 +262,7 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg *core.Message, state *st
} }
txContext := core.NewEVMTxContext(msg) txContext := core.NewEVMTxContext(msg)
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil) context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error, nil return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error, nil
} }

View file

@ -213,6 +213,7 @@ func TestStorageRangeAt(t *testing.T) {
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }
result, err := storageRangeAt(tr, test.start, test.limit) result, err := storageRangeAt(tr, test.start, test.limit)
if err != nil { if err != nil {
t.Error(err) t.Error(err)

View file

@ -140,6 +140,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil { if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil {
log.Error("Failed to recover state", "error", err) log.Error("Failed to recover state", "error", err)
} }
@ -147,6 +148,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
ethashConfig := config.Ethash ethashConfig := config.Ethash
ethashConfig.NotifyFull = config.Miner.NotifyFull ethashConfig.NotifyFull = config.Miner.NotifyFull
cliqueConfig, err := core.LoadCliqueConfig(chainDb, config.Genesis) cliqueConfig, err := core.LoadCliqueConfig(chainDb, config.Genesis)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -180,6 +182,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if gpoParams.Default == nil { if gpoParams.Default == nil {
gpoParams.Default = config.Miner.GasPrice gpoParams.Default = config.Miner.GasPrice
} }
ethereum.APIBackend.gpo = gasprice.NewOracle(ethereum.APIBackend, gpoParams) ethereum.APIBackend.gpo = gasprice.NewOracle(ethereum.APIBackend, gpoParams)
// Override the chain config with provided settings. // Override the chain config with provided settings.
@ -199,6 +202,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
// END: Bor changes // END: Bor changes
bcVersion := rawdb.ReadDatabaseVersion(chainDb) bcVersion := rawdb.ReadDatabaseVersion(chainDb)
var dbVer = "<nil>" var dbVer = "<nil>"
if bcVersion != nil { if bcVersion != nil {
dbVer = fmt.Sprintf("%d", *bcVersion) dbVer = fmt.Sprintf("%d", *bcVersion)
@ -259,6 +263,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if config.TxPool.Journal != "" { if config.TxPool.Journal != "" {
config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal)
} }
ethereum.txPool = txpool.NewTxPool(config.TxPool, ethereum.blockchain.Config(), ethereum.blockchain) ethereum.txPool = txpool.NewTxPool(config.TxPool, ethereum.blockchain.Config(), ethereum.blockchain)
// Permit the downloader to use the trie cache allowance during fast sync // Permit the downloader to use the trie cache allowance during fast sync
@ -267,6 +272,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if checkpoint == nil { if checkpoint == nil {
checkpoint = params.TrustedCheckpoints[ethereum.blockchain.Genesis().Hash()] checkpoint = params.TrustedCheckpoints[ethereum.blockchain.Genesis().Hash()]
} }
if ethereum.handler, err = newHandler(&handlerConfig{ if ethereum.handler, err = newHandler(&handlerConfig{
Database: chainDb, Database: chainDb,
Chain: ethereum.blockchain, Chain: ethereum.blockchain,
@ -294,6 +300,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
ethereum.snapDialCandidates, err = dnsclient.NewIterator(ethereum.config.SnapDiscoveryURLs...) ethereum.snapDialCandidates, err = dnsclient.NewIterator(ethereum.config.SnapDiscoveryURLs...)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -135,6 +135,7 @@ func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI {
if eth.BlockChain().Config().TerminalTotalDifficulty == nil { if eth.BlockChain().Config().TerminalTotalDifficulty == nil {
log.Warn("Engine API started but chain not configured for merge yet") log.Warn("Engine API started but chain not configured for merge yet")
} }
api := &ConsensusAPI{ api := &ConsensusAPI{
eth: eth, eth: eth,
remoteBlocks: newHeaderQueue(), remoteBlocks: newHeaderQueue(),
@ -143,6 +144,7 @@ func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI {
invalidTipsets: make(map[common.Hash]*types.Header), invalidTipsets: make(map[common.Hash]*types.Header),
} }
eth.Downloader().SetBadBlockCallback(api.setInvalidAncestor) eth.Downloader().SetBadBlockCallback(api.setInvalidAncestor)
go api.heartbeat() go api.heartbeat()
return api return api
@ -167,10 +169,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa
if payloadAttributes.Withdrawals != nil { if payloadAttributes.Withdrawals != nil {
return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1")) return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1"))
} }
if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp) { if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp) {
return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("forkChoiceUpdateV1 called post-shanghai")) return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("forkChoiceUpdateV1 called post-shanghai"))
} }
} }
return api.forkchoiceUpdated(update, payloadAttributes) return api.forkchoiceUpdated(update, payloadAttributes)
} }
@ -181,6 +185,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa
return engine.STATUS_INVALID, engine.InvalidParams.With(err) return engine.STATUS_INVALID, engine.InvalidParams.With(err)
} }
} }
return api.forkchoiceUpdated(update, payloadAttributes) return api.forkchoiceUpdated(update, payloadAttributes)
} }
@ -196,6 +201,7 @@ func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes)
return errors.New("missing withdrawals list") return errors.New("missing withdrawals list")
} }
} }
return nil return nil
} }
@ -242,7 +248,9 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
merger.ReachTTD() merger.ReachTTD()
api.eth.Downloader().Cancel() api.eth.Downloader().Cancel()
} }
context := []interface{}{"number", header.Number, "hash", header.Hash()} context := []interface{}{"number", header.Number, "hash", header.Hash()}
if update.FinalizedBlockHash != (common.Hash{}) { if update.FinalizedBlockHash != (common.Hash{}) {
if finalized == nil { if finalized == nil {
context = append(context, []interface{}{"finalized", "unknown"}...) context = append(context, []interface{}{"finalized", "unknown"}...)
@ -250,10 +258,13 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
context = append(context, []interface{}{"finalized", finalized.Number}...) context = append(context, []interface{}{"finalized", finalized.Number}...)
} }
} }
log.Info("Forkchoice requested sync to new head", context...) log.Info("Forkchoice requested sync to new head", context...)
if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header, finalized); err != nil { if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header, finalized); err != nil {
return engine.STATUS_SYNCING, err return engine.STATUS_SYNCING, err
} }
return engine.STATUS_SYNCING, nil return engine.STATUS_SYNCING, nil
} }
// Block is known locally, just sanity check that the beacon client does not // Block is known locally, just sanity check that the beacon client does not
@ -268,15 +279,18 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
log.Error("TDs unavailable for TTD check", "number", block.NumberU64(), "hash", update.HeadBlockHash, "td", td, "parent", block.ParentHash(), "ptd", ptd) log.Error("TDs unavailable for TTD check", "number", block.NumberU64(), "hash", update.HeadBlockHash, "td", td, "parent", block.ParentHash(), "ptd", ptd)
return engine.STATUS_INVALID, errors.New("TDs unavailable for TDD check") return engine.STATUS_INVALID, errors.New("TDs unavailable for TDD check")
} }
if td.Cmp(ttd) < 0 { if td.Cmp(ttd) < 0 {
log.Error("Refusing beacon update to pre-merge", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) log.Error("Refusing beacon update to pre-merge", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)))
return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
} }
if block.NumberU64() > 0 && ptd.Cmp(ttd) >= 0 { if block.NumberU64() > 0 && ptd.Cmp(ttd) >= 0 {
log.Error("Parent block is already post-ttd", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) log.Error("Parent block is already post-ttd", "number", block.NumberU64(), "hash", update.HeadBlockHash, "diff", block.Difficulty(), "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)))
return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
} }
} }
valid := func(id *engine.PayloadID) engine.ForkChoiceResponse { valid := func(id *engine.PayloadID) engine.ForkChoiceResponse {
return engine.ForkChoiceResponse{ return engine.ForkChoiceResponse{
PayloadStatus: engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &update.HeadBlockHash}, PayloadStatus: engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &update.HeadBlockHash},
@ -349,14 +363,18 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
if api.localBlocks.has(id) { if api.localBlocks.has(id) {
return valid(&id), nil return valid(&id), nil
} }
payload, err := api.eth.Miner().BuildPayload(args) payload, err := api.eth.Miner().BuildPayload(args)
if err != nil { if err != nil {
log.Error("Failed to build payload", "err", err) log.Error("Failed to build payload", "err", err)
return valid(nil), engine.InvalidPayloadAttributes.With(err) return valid(nil), engine.InvalidPayloadAttributes.With(err)
} }
api.localBlocks.put(id, payload) api.localBlocks.put(id, payload)
return valid(&id), nil return valid(&id), nil
} }
return valid(nil), nil return valid(nil), nil
} }
@ -387,6 +405,7 @@ func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.Transit
} }
return nil, fmt.Errorf("invalid terminal block hash") return nil, fmt.Errorf("invalid terminal block hash")
} }
return &engine.TransitionConfigurationV1{TerminalTotalDifficulty: (*hexutil.Big)(ttd)}, nil return &engine.TransitionConfigurationV1{TerminalTotalDifficulty: (*hexutil.Big)(ttd)}, nil
} }
@ -396,6 +415,7 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.Execu
if err != nil { if err != nil {
return nil, err return nil, err
} }
return data.ExecutionPayload, nil return data.ExecutionPayload, nil
} }
@ -418,6 +438,7 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl
if params.Withdrawals != nil { if params.Withdrawals != nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1")) return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1"))
} }
return api.newPayload(params) return api.newPayload(params)
} }
@ -430,6 +451,7 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
} else if params.Withdrawals != nil { } else if params.Withdrawals != nil {
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("non-nil withdrawals pre-shanghai")) return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("non-nil withdrawals pre-shanghai"))
} }
return api.newPayload(params) return api.newPayload(params)
} }
@ -466,6 +488,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
if block := api.eth.BlockChain().GetBlockByHash(params.BlockHash); block != nil { if block := api.eth.BlockChain().GetBlockByHash(params.BlockHash); block != nil {
log.Warn("Ignoring already known beacon payload", "number", params.Number, "hash", params.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0))) log.Warn("Ignoring already known beacon payload", "number", params.Number, "hash", params.BlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)))
hash := block.Hash() hash := block.Hash()
return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil
} }
// If this block was rejected previously, keep rejecting it // If this block was rejected previously, keep rejecting it
@ -489,10 +512,12 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
ttd = api.eth.BlockChain().Config().TerminalTotalDifficulty ttd = api.eth.BlockChain().Config().TerminalTotalDifficulty
gptd = api.eth.BlockChain().GetTd(parent.ParentHash(), parent.NumberU64()-1) gptd = api.eth.BlockChain().GetTd(parent.ParentHash(), parent.NumberU64()-1)
) )
if ptd.Cmp(ttd) < 0 { if ptd.Cmp(ttd) < 0 {
log.Warn("Ignoring pre-merge payload", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd) log.Warn("Ignoring pre-merge payload", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd)
return engine.INVALID_TERMINAL_BLOCK, nil return engine.INVALID_TERMINAL_BLOCK, nil
} }
if parent.Difficulty().BitLen() > 0 && gptd != nil && gptd.Cmp(ttd) >= 0 { if parent.Difficulty().BitLen() > 0 && gptd != nil && gptd.Cmp(ttd) >= 0 {
log.Error("Ignoring pre-merge parent block", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd) log.Error("Ignoring pre-merge parent block", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd)
return engine.INVALID_TERMINAL_BLOCK, nil return engine.INVALID_TERMINAL_BLOCK, nil
@ -511,6 +536,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
api.remoteBlocks.put(block.Hash(), block.Header()) api.remoteBlocks.put(block.Hash(), block.Header())
log.Warn("State not available, ignoring new payload") log.Warn("State not available, ignoring new payload")
return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil
} }
log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number) log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number)
@ -532,6 +558,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
api.eth.Downloader().Cancel() api.eth.Downloader().Cancel()
} }
hash := block.Hash() hash := block.Hash()
return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil
} }
@ -571,6 +598,7 @@ func (api *ConsensusAPI) delayPayloadImport(block *types.Block) (engine.PayloadS
// and cannot afford concurrent out-if-band modifications via imports. // and cannot afford concurrent out-if-band modifications via imports.
log.Warn("Ignoring payload while snap syncing", "number", block.NumberU64(), "hash", block.Hash()) log.Warn("Ignoring payload while snap syncing", "number", block.NumberU64(), "hash", block.Hash())
} }
return engine.PayloadStatusV1{Status: engine.SYNCING}, nil return engine.PayloadStatusV1{Status: engine.SYNCING}, nil
} }
@ -609,17 +637,20 @@ func (api *ConsensusAPI) checkInvalidAncestor(check common.Hash, head common.Has
delete(api.invalidTipsets, descendant) delete(api.invalidTipsets, descendant)
} }
} }
return nil return nil
} }
// Not too many failures yet, mark the head of the invalid chain as invalid // Not too many failures yet, mark the head of the invalid chain as invalid
if check != head { if check != head {
log.Warn("Marked new chain head as invalid", "hash", head, "badnumber", invalid.Number, "badhash", badHash) log.Warn("Marked new chain head as invalid", "hash", head, "badnumber", invalid.Number, "badhash", badHash)
for len(api.invalidTipsets) >= invalidTipsetsCap { for len(api.invalidTipsets) >= invalidTipsetsCap {
for key := range api.invalidTipsets { for key := range api.invalidTipsets {
delete(api.invalidTipsets, key) delete(api.invalidTipsets, key)
break break
} }
} }
api.invalidTipsets[head] = invalid api.invalidTipsets[head] = invalid
} }
// If the last valid hash is the terminal pow block, return 0x0 for latest valid hash // If the last valid hash is the terminal pow block, return 0x0 for latest valid hash
@ -627,7 +658,9 @@ func (api *ConsensusAPI) checkInvalidAncestor(check common.Hash, head common.Has
if header := api.eth.BlockChain().GetHeader(invalid.ParentHash, invalid.Number.Uint64()-1); header != nil && header.Difficulty.Sign() != 0 { if header := api.eth.BlockChain().GetHeader(invalid.ParentHash, invalid.Number.Uint64()-1); header != nil && header.Difficulty.Sign() != 0 {
lastValid = &common.Hash{} lastValid = &common.Hash{}
} }
failure := "links to previously rejected block" failure := "links to previously rejected block"
return &engine.PayloadStatusV1{ return &engine.PayloadStatusV1{
Status: engine.INVALID, Status: engine.INVALID,
LatestValidHash: lastValid, LatestValidHash: lastValid,
@ -648,6 +681,7 @@ func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.Pa
} }
} }
errorMsg := err.Error() errorMsg := err.Error()
return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &currentHash, ValidationError: &errorMsg} return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &currentHash, ValidationError: &errorMsg}
} }
@ -702,8 +736,10 @@ func (api *ConsensusAPI) heartbeat() {
} else { } else {
log.Warn("Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!") log.Warn("Beacon client online, but no consensus updates received in a while. Please fix your beacon client to follow the chain!")
} }
offlineLogged = time.Now() offlineLogged = time.Now()
} }
continue continue
} }
} }
@ -718,10 +754,12 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
// of block bodies by the engine api. // of block bodies by the engine api.
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 { func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
var bodies = make([]*engine.ExecutionPayloadBodyV1, len(hashes)) var bodies = make([]*engine.ExecutionPayloadBodyV1, len(hashes))
for i, hash := range hashes { for i, hash := range hashes {
block := api.eth.BlockChain().GetBlockByHash(hash) block := api.eth.BlockChain().GetBlockByHash(hash)
bodies[i] = getBody(block) bodies[i] = getBody(block)
} }
return bodies return bodies
} }
@ -731,20 +769,25 @@ func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64)
if start == 0 || count == 0 { if start == 0 || count == 0 {
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count)) return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
} }
if count > 1024 { if count > 1024 {
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count)) return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count))
} }
// limit count up until current // limit count up until current
current := api.eth.BlockChain().CurrentBlock().Number.Uint64() current := api.eth.BlockChain().CurrentBlock().Number.Uint64()
last := uint64(start) + uint64(count) - 1 last := uint64(start) + uint64(count) - 1
if last > current { if last > current {
last = current last = current
} }
bodies := make([]*engine.ExecutionPayloadBodyV1, 0, uint64(count)) bodies := make([]*engine.ExecutionPayloadBodyV1, 0, uint64(count))
for i := uint64(start); i <= last; i++ { for i := uint64(start); i <= last; i++ {
block := api.eth.BlockChain().GetBlockByNumber(i) block := api.eth.BlockChain().GetBlockByNumber(i)
bodies = append(bodies, getBody(block)) bodies = append(bodies, getBody(block))
} }
return bodies, nil return bodies, nil
} }

View file

@ -61,6 +61,7 @@ var (
func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) { func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
config := *params.AllEthashProtocolChanges config := *params.AllEthashProtocolChanges
engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker())) engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker()))
if merged { if merged {
config.TerminalTotalDifficulty = common.Big0 config.TerminalTotalDifficulty = common.Big0
config.TerminalTotalDifficultyPassed = true config.TerminalTotalDifficultyPassed = true
@ -78,6 +79,7 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
generate := func(i int, g *core.BlockGen) { generate := func(i int, g *core.BlockGen) {
g.OffsetTime(5) g.OffsetTime(5)
g.SetExtra([]byte("test")) g.SetExtra([]byte("test"))
tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil), types.LatestSigner(&config), testKey) tx, _ := types.SignTx(types.NewTransaction(testNonce, common.HexToAddress("0x9a9070028361F7AAbeB3f2F2Dc07F82C4a98A02a"), big.NewInt(1), params.TxGas, big.NewInt(params.InitialBaseFee*2), nil), types.LatestSigner(&config), testKey)
g.AddTx(tx) g.AddTx(tx)
testNonce++ testNonce++
@ -89,6 +91,7 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
for _, b := range blocks { for _, b := range blocks {
totalDifficulty.Add(totalDifficulty, b.Difficulty()) totalDifficulty.Add(totalDifficulty, b.Difficulty())
} }
config.TerminalTotalDifficulty = totalDifficulty config.TerminalTotalDifficulty = totalDifficulty
} }
@ -109,6 +112,7 @@ func TestEth2AssembleBlock(t *testing.T) {
t.Fatalf("error signing transaction, err=%v", err) t.Fatalf("error signing transaction, err=%v", err)
} }
ethservice.TxPool().AddLocal(tx) ethservice.TxPool().AddLocal(tx)
blockParams := engine.PayloadAttributes{ blockParams := engine.PayloadAttributes{
Timestamp: blocks[9].Time() + 5, Timestamp: blocks[9].Time() + 5,
} }
@ -127,12 +131,15 @@ func assembleWithTransactions(api *ConsensusAPI, parentHash common.Hash, params
if err != nil { if err != nil {
return nil, err return nil, err
} }
if have, want := len(execData.Transactions), want; have != want { if have, want := len(execData.Transactions), want; have != want {
err = fmt.Errorf("invalid number of transactions, have %d want %d", have, want) err = fmt.Errorf("invalid number of transactions, have %d want %d", have, want)
continue continue
} }
return execData, nil return execData, nil
} }
return nil, err return nil, err
} }
@ -147,6 +154,7 @@ func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) {
// Put the 10th block's tx in the pool and produce a new block // Put the 10th block's tx in the pool and produce a new block
api.eth.TxPool().AddRemotesSync(blocks[9].Transactions()) api.eth.TxPool().AddRemotesSync(blocks[9].Transactions())
blockParams := engine.PayloadAttributes{ blockParams := engine.PayloadAttributes{
Timestamp: blocks[8].Time() + 5, Timestamp: blocks[8].Time() + 5,
} }
@ -180,12 +188,14 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
// We need to properly set the terminal total difficulty // We need to properly set the terminal total difficulty
genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[9].Difficulty()) genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[9].Difficulty())
n, ethservice := startEthService(t, genesis, blocks[:9]) n, ethservice := startEthService(t, genesis, blocks[:9])
defer n.Close() defer n.Close()
api := NewConsensusAPI(ethservice) api := NewConsensusAPI(ethservice)
// Put the 10th block's tx in the pool and produce a new block // Put the 10th block's tx in the pool and produce a new block
ethservice.TxPool().AddLocals(blocks[9].Transactions()) ethservice.TxPool().AddLocals(blocks[9].Transactions())
blockParams := engine.PayloadAttributes{ blockParams := engine.PayloadAttributes{
Timestamp: blocks[8].Time() + 5, Timestamp: blocks[8].Time() + 5,
} }
@ -195,11 +205,13 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
FinalizedBlockHash: common.Hash{}, FinalizedBlockHash: common.Hash{},
} }
_, err := api.ForkchoiceUpdatedV1(fcState, &blockParams) _, err := api.ForkchoiceUpdatedV1(fcState, &blockParams)
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
// give the payload some time to be built // give the payload some time to be built
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
payloadID := (&miner.BuildPayloadArgs{ payloadID := (&miner.BuildPayloadArgs{
Parent: fcState.HeadBlockHash, Parent: fcState.HeadBlockHash,
Timestamp: blockParams.Timestamp, Timestamp: blockParams.Timestamp,
@ -207,17 +219,21 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
Random: blockParams.Random, Random: blockParams.Random,
}).Id() }).Id()
execData, err := api.GetPayloadV1(payloadID) execData, err := api.GetPayloadV1(payloadID)
if err != nil { if err != nil {
t.Fatalf("error getting payload, err=%v", err) t.Fatalf("error getting payload, err=%v", err)
} }
if len(execData.Transactions) != blocks[9].Transactions().Len() { if len(execData.Transactions) != blocks[9].Transactions().Len() {
t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions)) t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions))
} }
// Test invalid payloadID // Test invalid payloadID
var invPayload engine.PayloadID var invPayload engine.PayloadID
copy(invPayload[:], payloadID[:]) copy(invPayload[:], payloadID[:])
invPayload[0] = ^invPayload[0] invPayload[0] = ^invPayload[0]
_, err = api.GetPayloadV1(invPayload) _, err = api.GetPayloadV1(invPayload)
if err == nil { if err == nil {
t.Fatal("expected error retrieving invalid payload") t.Fatal("expected error retrieving invalid payload")
} }
@ -287,6 +303,7 @@ func TestInvalidPayloadTimestamp(t *testing.T) {
func TestEth2NewBlock(t *testing.T) { func TestEth2NewBlock(t *testing.T) {
t.Skip("ETH2 in Bor") t.Skip("ETH2 in Bor")
genesis, preMergeBlocks := generateMergeChain(10, false) genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks) n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close() defer n.Close()
@ -316,11 +333,13 @@ func TestEth2NewBlock(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to create the executable data %v", err) t.Fatalf("Failed to create the executable data %v", err)
} }
block, err := engine.ExecutableDataToBlock(*execData) block, err := engine.ExecutableDataToBlock(*execData)
if err != nil { if err != nil {
t.Fatalf("Failed to convert executable data to block %v", err) t.Fatalf("Failed to convert executable data to block %v", err)
} }
newResp, err := api.NewPayloadV1(*execData) newResp, err := api.NewPayloadV1(*execData)
switch { switch {
case err != nil: case err != nil:
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
@ -330,14 +349,17 @@ func TestEth2NewBlock(t *testing.T) {
t.Fatalf("Chain head shouldn't be updated") t.Fatalf("Chain head shouldn't be updated")
} }
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0) checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
fcState := engine.ForkchoiceStateV1{ fcState := engine.ForkchoiceStateV1{
HeadBlockHash: block.Hash(), HeadBlockHash: block.Hash(),
SafeBlockHash: block.Hash(), SafeBlockHash: block.Hash(),
FinalizedBlockHash: block.Hash(), FinalizedBlockHash: block.Hash(),
} }
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want { if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want {
t.Fatalf("Chain head should be updated, have %d want %d", have, want) t.Fatalf("Chain head should be updated, have %d want %d", have, want)
} }
@ -350,22 +372,28 @@ func TestEth2NewBlock(t *testing.T) {
var ( var (
head = ethservice.BlockChain().CurrentBlock().Number.Uint64() head = ethservice.BlockChain().CurrentBlock().Number.Uint64()
) )
parent = preMergeBlocks[len(preMergeBlocks)-1] parent = preMergeBlocks[len(preMergeBlocks)-1]
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{
Timestamp: parent.Time() + 6, Timestamp: parent.Time() + 6,
}) })
if err != nil { if err != nil {
t.Fatalf("Failed to create the executable data %v", err) t.Fatalf("Failed to create the executable data %v", err)
} }
block, err := engine.ExecutableDataToBlock(*execData) block, err := engine.ExecutableDataToBlock(*execData)
if err != nil { if err != nil {
t.Fatalf("Failed to convert executable data to block %v", err) t.Fatalf("Failed to convert executable data to block %v", err)
} }
newResp, err := api.NewPayloadV1(*execData) newResp, err := api.NewPayloadV1(*execData)
if err != nil || newResp.Status != "VALID" { if err != nil || newResp.Status != "VALID" {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != head { if ethservice.BlockChain().CurrentBlock().Number.Uint64() != head {
t.Fatalf("Chain head shouldn't be updated") t.Fatalf("Chain head shouldn't be updated")
} }
@ -375,9 +403,11 @@ func TestEth2NewBlock(t *testing.T) {
SafeBlockHash: block.Hash(), SafeBlockHash: block.Hash(),
FinalizedBlockHash: block.Hash(), FinalizedBlockHash: block.Hash(),
} }
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64() { if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64() {
t.Fatalf("Chain head should be updated") t.Fatalf("Chain head should be updated")
} }
@ -487,38 +517,48 @@ func TestFullAPI(t *testing.T) {
func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal) []*types.Header { func setupBlocks(t *testing.T, ethservice *eth.Ethereum, n int, parent *types.Header, callback func(parent *types.Header), withdrawals [][]*types.Withdrawal) []*types.Header {
api := NewConsensusAPI(ethservice) api := NewConsensusAPI(ethservice)
var blocks []*types.Header var blocks []*types.Header
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
callback(parent) callback(parent)
var w []*types.Withdrawal var w []*types.Withdrawal
if withdrawals != nil { if withdrawals != nil {
w = withdrawals[i] w = withdrawals[i]
} }
payload := getNewPayload(t, api, parent, w) payload := getNewPayload(t, api, parent, w)
execResp, err := api.NewPayloadV2(*payload) execResp, err := api.NewPayloadV2(*payload)
if err != nil { if err != nil {
t.Fatalf("can't execute payload: %v", err) t.Fatalf("can't execute payload: %v", err)
} }
if execResp.Status != engine.VALID { if execResp.Status != engine.VALID {
t.Fatalf("invalid status: %v", execResp.Status) t.Fatalf("invalid status: %v", execResp.Status)
} }
fcState := engine.ForkchoiceStateV1{ fcState := engine.ForkchoiceStateV1{
HeadBlockHash: payload.BlockHash, HeadBlockHash: payload.BlockHash,
SafeBlockHash: payload.ParentHash, SafeBlockHash: payload.ParentHash,
FinalizedBlockHash: payload.ParentHash, FinalizedBlockHash: payload.ParentHash,
} }
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number {
t.Fatal("Chain head should be updated") t.Fatal("Chain head should be updated")
} }
if ethservice.BlockChain().CurrentFinalBlock().Number.Uint64() != payload.Number-1 { if ethservice.BlockChain().CurrentFinalBlock().Number.Uint64() != payload.Number-1 {
t.Fatal("Finalized block should be updated") t.Fatal("Finalized block should be updated")
} }
parent = ethservice.BlockChain().CurrentBlock() parent = ethservice.BlockChain().CurrentBlock()
blocks = append(blocks, parent) blocks = append(blocks, parent)
} }
return blocks return blocks
} }
@ -588,6 +628,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false) genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks) n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close() defer n.Close()
var ( var (
@ -597,6 +638,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
// This EVM code generates a log when the contract is created. // This EVM code generates a log when the contract is created.
logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
) )
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
statedb, _ := ethservice.BlockChain().StateAt(parent.Root) statedb, _ := ethservice.BlockChain().StateAt(parent.Root)
tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{ tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{
@ -607,6 +649,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
Data: logCode, Data: logCode,
}) })
ethservice.TxPool().AddRemotesSync([]*types.Transaction{tx}) ethservice.TxPool().AddRemotesSync([]*types.Transaction{tx})
var ( var (
params = engine.PayloadAttributes{ params = engine.PayloadAttributes{
Timestamp: parent.Time + 1, Timestamp: parent.Time + 1,
@ -622,45 +665,59 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
resp engine.ForkChoiceResponse resp engine.ForkChoiceResponse
err error err error
) )
for i := 0; ; i++ { for i := 0; ; i++ {
if resp, err = api.ForkchoiceUpdatedV1(fcState, &params); err != nil { if resp, err = api.ForkchoiceUpdatedV1(fcState, &params); err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
if resp.PayloadStatus.Status != engine.VALID { if resp.PayloadStatus.Status != engine.VALID {
t.Fatalf("error preparing payload, invalid status: %v", resp.PayloadStatus.Status) t.Fatalf("error preparing payload, invalid status: %v", resp.PayloadStatus.Status)
} }
// give the payload some time to be built // give the payload some time to be built
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
if payload, err = api.GetPayloadV1(*resp.PayloadID); err != nil { if payload, err = api.GetPayloadV1(*resp.PayloadID); err != nil {
t.Fatalf("can't get payload: %v", err) t.Fatalf("can't get payload: %v", err)
} }
if len(payload.Transactions) > 0 { if len(payload.Transactions) > 0 {
break break
} }
// No luck this time we need to update the params and try again. // No luck this time we need to update the params and try again.
params.Timestamp = params.Timestamp + 1 params.Timestamp = params.Timestamp + 1
if i > 10 { if i > 10 {
t.Fatalf("payload should not be empty") t.Fatalf("payload should not be empty")
} }
} }
execResp, err := api.NewPayloadV1(*payload) execResp, err := api.NewPayloadV1(*payload)
if err != nil { if err != nil {
t.Fatalf("can't execute payload: %v", err) t.Fatalf("can't execute payload: %v", err)
} }
if execResp.Status != engine.VALID { if execResp.Status != engine.VALID {
t.Fatalf("invalid status: %v", execResp.Status) t.Fatalf("invalid status: %v", execResp.Status)
} }
fcState = engine.ForkchoiceStateV1{ fcState = engine.ForkchoiceStateV1{
HeadBlockHash: payload.BlockHash, HeadBlockHash: payload.BlockHash,
SafeBlockHash: payload.ParentHash, SafeBlockHash: payload.ParentHash,
FinalizedBlockHash: payload.ParentHash, FinalizedBlockHash: payload.ParentHash,
} }
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil { if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
t.Fatalf("Failed to insert block: %v", err) t.Fatalf("Failed to insert block: %v", err)
} }
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number { if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number {
t.Fatalf("Chain head should be updated") t.Fatalf("Chain head should be updated")
} }
parent = ethservice.BlockChain().CurrentBlock() parent = ethservice.BlockChain().CurrentBlock()
} }
} }
@ -674,9 +731,11 @@ func assembleBlock(api *ConsensusAPI, parentHash common.Hash, params *engine.Pay
Withdrawals: params.Withdrawals, Withdrawals: params.Withdrawals,
} }
payload, err := api.eth.Miner().BuildPayload(args) payload, err := api.eth.Miner().BuildPayload(args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return payload.ResolveFull().ExecutionPayload, nil return payload.ResolveFull().ExecutionPayload, nil
} }
@ -685,6 +744,7 @@ func TestEmptyBlocks(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false) genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks) n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close() defer n.Close()
commonAncestor := ethservice.BlockChain().CurrentBlock() commonAncestor := ethservice.BlockChain().CurrentBlock()
@ -700,9 +760,11 @@ func TestEmptyBlocks(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if status.Status != engine.VALID { if status.Status != engine.VALID {
t.Errorf("invalid status: expected VALID got: %v", status.Status) t.Errorf("invalid status: expected VALID got: %v", status.Status)
} }
if !bytes.Equal(status.LatestValidHash[:], payload.BlockHash[:]) { if !bytes.Equal(status.LatestValidHash[:], payload.BlockHash[:]) {
t.Fatalf("invalid LVH: got %v want %v", status.LatestValidHash, payload.BlockHash) t.Fatalf("invalid LVH: got %v want %v", status.LatestValidHash, payload.BlockHash)
} }
@ -716,6 +778,7 @@ func TestEmptyBlocks(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if status.Status != engine.INVALID { if status.Status != engine.INVALID {
t.Errorf("invalid status: expected INVALID got: %v", status.Status) t.Errorf("invalid status: expected INVALID got: %v", status.Status)
} }
@ -734,9 +797,11 @@ func TestEmptyBlocks(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if status.Status != engine.SYNCING { if status.Status != engine.SYNCING {
t.Errorf("invalid status: expected SYNCING got: %v", status.Status) t.Errorf("invalid status: expected SYNCING got: %v", status.Status)
} }
if status.LatestValidHash != nil { if status.LatestValidHash != nil {
t.Fatalf("invalid LVH: got %v wanted nil", status.LatestValidHash) t.Fatalf("invalid LVH: got %v wanted nil", status.LatestValidHash)
} }
@ -756,6 +821,7 @@ func getNewPayload(t *testing.T, api *ConsensusAPI, parent *types.Header, withdr
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return payload return payload
} }
@ -765,6 +831,7 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData {
txs, _ := decodeTransactions(data.Transactions) txs, _ := decodeTransactions(data.Transactions)
number := big.NewInt(0) number := big.NewInt(0)
number.SetUint64(data.Number) number.SetUint64(data.Number)
header := &types.Header{ header := &types.Header{
ParentHash: data.ParentHash, ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
@ -784,18 +851,22 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData {
} }
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
data.BlockHash = block.Hash() data.BlockHash = block.Hash()
return data return data
} }
func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) { func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
var txs = make([]*types.Transaction, len(enc)) var txs = make([]*types.Transaction, len(enc))
for i, encTx := range enc { for i, encTx := range enc {
var tx types.Transaction var tx types.Transaction
if err := tx.UnmarshalBinary(encTx); err != nil { if err := tx.UnmarshalBinary(encTx); err != nil {
return nil, fmt.Errorf("invalid transaction %d: %v", i, err) return nil, fmt.Errorf("invalid transaction %d: %v", i, err)
} }
txs[i] = &tx txs[i] = &tx
} }
return txs, nil return txs, nil
} }
@ -806,13 +877,16 @@ func TestTrickRemoteBlockCache(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false) genesis, preMergeBlocks := generateMergeChain(10, false)
nodeA, ethserviceA := startEthService(t, genesis, preMergeBlocks) nodeA, ethserviceA := startEthService(t, genesis, preMergeBlocks)
nodeB, ethserviceB := startEthService(t, genesis, preMergeBlocks) nodeB, ethserviceB := startEthService(t, genesis, preMergeBlocks)
defer nodeA.Close() defer nodeA.Close()
defer nodeB.Close() defer nodeB.Close()
for nodeB.Server().NodeInfo().Ports.Listener == 0 { for nodeB.Server().NodeInfo().Ports.Listener == 0 {
time.Sleep(250 * time.Millisecond) time.Sleep(250 * time.Millisecond)
} }
nodeA.Server().AddPeer(nodeB.Server().Self()) nodeA.Server().AddPeer(nodeB.Server().Self())
nodeB.Server().AddPeer(nodeA.Server().Self()) nodeB.Server().AddPeer(nodeA.Server().Self())
apiA := NewConsensusAPI(ethserviceA) apiA := NewConsensusAPI(ethserviceA)
apiB := NewConsensusAPI(ethserviceB) apiB := NewConsensusAPI(ethserviceB)
@ -850,6 +924,7 @@ func TestTrickRemoteBlockCache(t *testing.T) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
if status.Status == engine.VALID { if status.Status == engine.VALID {
t.Error("invalid status: VALID on an invalid chain") t.Error("invalid status: VALID on an invalid chain")
} }
@ -858,9 +933,11 @@ func TestTrickRemoteBlockCache(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if resp.PayloadStatus.Status == engine.VALID { if resp.PayloadStatus.Status == engine.VALID {
t.Error("invalid status: VALID on an invalid chain") t.Error("invalid status: VALID on an invalid chain")
} }
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
} }
@ -871,6 +948,7 @@ func TestInvalidBloom(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false) genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks) n, ethservice := startEthService(t, genesis, preMergeBlocks)
ethservice.Merger().ReachTTD() ethservice.Merger().ReachTTD()
defer n.Close() defer n.Close()
commonAncestor := ethservice.BlockChain().CurrentBlock() commonAncestor := ethservice.BlockChain().CurrentBlock()
@ -883,9 +961,11 @@ func TestInvalidBloom(t *testing.T) {
payload := getNewPayload(t, api, commonAncestor, nil) payload := getNewPayload(t, api, commonAncestor, nil)
payload.LogsBloom = append(payload.LogsBloom, byte(1)) payload.LogsBloom = append(payload.LogsBloom, byte(1))
status, err := api.NewPayloadV1(*payload) status, err := api.NewPayloadV1(*payload)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if status.Status != engine.INVALID { if status.Status != engine.INVALID {
t.Errorf("invalid status: expected INVALID got: %v", status.Status) t.Errorf("invalid status: expected INVALID got: %v", status.Status)
} }
@ -896,7 +976,9 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(100, false) genesis, preMergeBlocks := generateMergeChain(100, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks) n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close() defer n.Close()
api := NewConsensusAPI(ethservice) api := NewConsensusAPI(ethservice)
// Test parent already post TTD in FCU // Test parent already post TTD in FCU
@ -907,9 +989,11 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
FinalizedBlockHash: common.Hash{}, FinalizedBlockHash: common.Hash{},
} }
resp, err := api.ForkchoiceUpdatedV1(fcState, nil) resp, err := api.ForkchoiceUpdatedV1(fcState, nil)
if err != nil { if err != nil {
t.Fatalf("error sending forkchoice, err=%v", err) t.Fatalf("error sending forkchoice, err=%v", err)
} }
if resp.PayloadStatus != engine.INVALID_TERMINAL_BLOCK { if resp.PayloadStatus != engine.INVALID_TERMINAL_BLOCK {
t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status) t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status)
} }
@ -922,9 +1006,11 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
FeeRecipient: parent.Coinbase(), FeeRecipient: parent.Coinbase(),
} }
payload, err := api.eth.Miner().BuildPayload(args) payload, err := api.eth.Miner().BuildPayload(args)
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
data := *payload.Resolve().ExecutionPayload data := *payload.Resolve().ExecutionPayload
// We need to recompute the blockhash, since the miner computes a wrong (correct) blockhash // We need to recompute the blockhash, since the miner computes a wrong (correct) blockhash
txs, _ := decodeTransactions(data.Transactions) txs, _ := decodeTransactions(data.Transactions)
@ -952,6 +1038,7 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("error sending NewPayload, err=%v", err) t.Fatalf("error sending NewPayload, err=%v", err)
} }
if resp2 != engine.INVALID_TERMINAL_BLOCK { if resp2 != engine.INVALID_TERMINAL_BLOCK {
t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status) t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status)
} }
@ -965,12 +1052,14 @@ func TestSimultaneousNewBlock(t *testing.T) {
genesis, preMergeBlocks := generateMergeChain(10, false) genesis, preMergeBlocks := generateMergeChain(10, false)
n, ethservice := startEthService(t, genesis, preMergeBlocks) n, ethservice := startEthService(t, genesis, preMergeBlocks)
defer n.Close() defer n.Close()
var ( var (
api = NewConsensusAPI(ethservice) api = NewConsensusAPI(ethservice)
parent = preMergeBlocks[len(preMergeBlocks)-1] parent = preMergeBlocks[len(preMergeBlocks)-1]
) )
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{ execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{
Timestamp: parent.Time() + 5, Timestamp: parent.Time() + 5,
@ -1005,13 +1094,17 @@ func TestSimultaneousNewBlock(t *testing.T) {
t.Fatal(testErr) t.Fatal(testErr)
} }
} }
block, err := engine.ExecutableDataToBlock(*execData) block, err := engine.ExecutableDataToBlock(*execData)
if err != nil { if err != nil {
t.Fatalf("Failed to convert executable data to block %v", err) t.Fatalf("Failed to convert executable data to block %v", err)
} }
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1 { if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1 {
t.Fatalf("Chain head shouldn't be updated") t.Fatalf("Chain head shouldn't be updated")
} }
fcState := engine.ForkchoiceStateV1{ fcState := engine.ForkchoiceStateV1{
HeadBlockHash: block.Hash(), HeadBlockHash: block.Hash(),
SafeBlockHash: block.Hash(), SafeBlockHash: block.Hash(),
@ -1040,9 +1133,11 @@ func TestSimultaneousNewBlock(t *testing.T) {
t.Fatal(testErr) t.Fatal(testErr)
} }
} }
if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want { if have, want := ethservice.BlockChain().CurrentBlock().Number.Uint64(), block.NumberU64(); have != want {
t.Fatalf("Chain head should be updated, have %d want %d", have, want) t.Fatalf("Chain head should be updated, have %d want %d", have, want)
} }
parent = block parent = block
} }
} }
@ -1059,6 +1154,7 @@ func TestWithdrawals(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks) n, ethservice := startEthService(t, genesis, blocks)
ethservice.Merger().ReachTTD() ethservice.Merger().ReachTTD()
defer n.Close() defer n.Close()
api := NewConsensusAPI(ethservice) api := NewConsensusAPI(ethservice)
@ -1073,9 +1169,11 @@ func TestWithdrawals(t *testing.T) {
HeadBlockHash: parent.Hash(), HeadBlockHash: parent.Hash(),
} }
resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams) resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams)
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
if resp.PayloadStatus.Status != engine.VALID { if resp.PayloadStatus.Status != engine.VALID {
t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID) t.Fatalf("unexpected status (got: %s, want: %s)", resp.PayloadStatus.Status, engine.VALID)
} }
@ -1089,9 +1187,11 @@ func TestWithdrawals(t *testing.T) {
Withdrawals: blockParams.Withdrawals, Withdrawals: blockParams.Withdrawals,
}).Id() }).Id()
execData, err := api.GetPayloadV2(payloadID) execData, err := api.GetPayloadV2(payloadID)
if err != nil { if err != nil {
t.Fatalf("error getting payload, err=%v", err) t.Fatalf("error getting payload, err=%v", err)
} }
if execData.ExecutionPayload.StateRoot != parent.Root { if execData.ExecutionPayload.StateRoot != parent.Root {
t.Fatalf("mismatch state roots (got: %s, want: %s)", execData.ExecutionPayload.StateRoot, blocks[8].Root()) t.Fatalf("mismatch state roots (got: %s, want: %s)", execData.ExecutionPayload.StateRoot, blocks[8].Root())
} }
@ -1123,6 +1223,7 @@ func TestWithdrawals(t *testing.T) {
} }
fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash
_, err = api.ForkchoiceUpdatedV2(fcState, &blockParams) _, err = api.ForkchoiceUpdatedV2(fcState, &blockParams)
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
@ -1136,9 +1237,11 @@ func TestWithdrawals(t *testing.T) {
Withdrawals: blockParams.Withdrawals, Withdrawals: blockParams.Withdrawals,
}).Id() }).Id()
execData, err = api.GetPayloadV2(payloadID) execData, err = api.GetPayloadV2(payloadID)
if err != nil { if err != nil {
t.Fatalf("error getting payload, err=%v", err) t.Fatalf("error getting payload, err=%v", err)
} }
if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil { if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil {
t.Fatalf("error validating payload: %v", err) t.Fatalf("error validating payload: %v", err)
} else if status.Status != engine.VALID { } else if status.Status != engine.VALID {
@ -1148,6 +1251,7 @@ func TestWithdrawals(t *testing.T) {
// 11: set block as head. // 11: set block as head.
fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash
_, err = api.ForkchoiceUpdatedV2(fcState, nil) _, err = api.ForkchoiceUpdatedV2(fcState, nil)
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
@ -1157,6 +1261,7 @@ func TestWithdrawals(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("unable to load db: %v", err) t.Fatalf("unable to load db: %v", err)
} }
for i, w := range blockParams.Withdrawals { for i, w := range blockParams.Withdrawals {
// w.Amount is in gwei, balance in wei // w.Amount is in gwei, balance in wei
if db.GetBalance(w.Address).Uint64() != w.Amount*params.GWei { if db.GetBalance(w.Address).Uint64() != w.Amount*params.GWei {
@ -1175,6 +1280,7 @@ func TestNilWithdrawals(t *testing.T) {
n, ethservice := startEthService(t, genesis, blocks) n, ethservice := startEthService(t, genesis, blocks)
ethservice.Merger().ReachTTD() ethservice.Merger().ReachTTD()
defer n.Close() defer n.Close()
api := NewConsensusAPI(ethservice) api := NewConsensusAPI(ethservice)
@ -1185,6 +1291,7 @@ func TestNilWithdrawals(t *testing.T) {
blockParams engine.PayloadAttributes blockParams engine.PayloadAttributes
wantErr bool wantErr bool
} }
tests := []test{ tests := []test{
// Before Shanghai // Before Shanghai
{ {
@ -1254,8 +1361,10 @@ func TestNilWithdrawals(t *testing.T) {
if err == nil { if err == nil {
t.Fatal("wanted error on fcuv2 with invalid withdrawals") t.Fatal("wanted error on fcuv2 with invalid withdrawals")
} }
continue continue
} }
if err != nil { if err != nil {
t.Fatalf("error preparing payload, err=%v", err) t.Fatalf("error preparing payload, err=%v", err)
} }
@ -1268,9 +1377,11 @@ func TestNilWithdrawals(t *testing.T) {
Random: test.blockParams.Random, Random: test.blockParams.Random,
}).Id() }).Id()
execData, err := api.GetPayloadV2(payloadID) execData, err := api.GetPayloadV2(payloadID)
if err != nil { if err != nil {
t.Fatalf("error getting payload, err=%v", err) t.Fatalf("error getting payload, err=%v", err)
} }
if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil { if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil {
t.Fatalf("error validating payload: %v", err) t.Fatalf("error validating payload: %v", err)
} else if status.Status != engine.VALID { } else if status.Status != engine.VALID {
@ -1304,9 +1415,12 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
withdrawals := make([][]*types.Withdrawal, 10) withdrawals := make([][]*types.Withdrawal, 10)
withdrawals[0] = nil // should be filtered out by miner withdrawals[0] = nil // should be filtered out by miner
withdrawals[1] = make([]*types.Withdrawal, 0) withdrawals[1] = make([]*types.Withdrawal, 0)
for i := 2; i < len(withdrawals); i++ { for i := 2; i < len(withdrawals); i++ {
addr := make([]byte, 20) addr := make([]byte, 20)
crand.Read(addr) crand.Read(addr)
withdrawals[i] = []*types.Withdrawal{ withdrawals[i] = []*types.Withdrawal{
{Index: rand.Uint64(), Validator: rand.Uint64(), Amount: rand.Uint64(), Address: common.BytesToAddress(addr)}, {Index: rand.Uint64(), Validator: rand.Uint64(), Amount: rand.Uint64(), Address: common.BytesToAddress(addr)},
} }
@ -1314,9 +1428,11 @@ func setupBodies(t *testing.T) (*node.Node, *eth.Ethereum, []*types.Block) {
postShanghaiHeaders := setupBlocks(t, ethservice, 10, parent, callback, withdrawals) postShanghaiHeaders := setupBlocks(t, ethservice, 10, parent, callback, withdrawals)
postShanghaiBlocks := make([]*types.Block, len(postShanghaiHeaders)) postShanghaiBlocks := make([]*types.Block, len(postShanghaiHeaders))
for i, header := range postShanghaiHeaders { for i, header := range postShanghaiHeaders {
postShanghaiBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64()) postShanghaiBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64())
} }
return n, ethservice, append(blocks, postShanghaiBlocks...) return n, ethservice, append(blocks, postShanghaiBlocks...)
} }
@ -1325,6 +1441,7 @@ func allHashes(blocks []*types.Block) []common.Hash {
for _, b := range blocks { for _, b := range blocks {
hashes = append(hashes, b.Hash()) hashes = append(hashes, b.Hash())
} }
return hashes return hashes
} }
func allBodies(blocks []*types.Block) []*types.Body { func allBodies(blocks []*types.Block) []*types.Body {
@ -1332,6 +1449,7 @@ func allBodies(blocks []*types.Block) []*types.Body {
for _, b := range blocks { for _, b := range blocks {
bodies = append(bodies, b.Body()) bodies = append(bodies, b.Body())
} }
return bodies return bodies
} }
@ -1340,6 +1458,7 @@ func TestGetBlockBodiesByHash(t *testing.T) {
node, eth, blocks := setupBodies(t) node, eth, blocks := setupBodies(t)
api := NewConsensusAPI(eth) api := NewConsensusAPI(eth)
defer node.Close() defer node.Close()
tests := []struct { tests := []struct {
@ -1398,6 +1517,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
node, eth, blocks := setupBodies(t) node, eth, blocks := setupBodies(t)
api := NewConsensusAPI(eth) api := NewConsensusAPI(eth)
defer node.Close() defer node.Close()
tests := []struct { tests := []struct {
@ -1464,6 +1584,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if len(result) == len(test.results) { if len(result) == len(test.results) {
for i, r := range result { for i, r := range result {
if !equalBody(test.results[i], r) { if !equalBody(test.results[i], r) {
@ -1481,7 +1602,9 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
node, eth, _ := setupBodies(t) node, eth, _ := setupBodies(t)
api := NewConsensusAPI(eth) api := NewConsensusAPI(eth)
defer node.Close() defer node.Close()
tests := []struct { tests := []struct {
start hexutil.Uint64 start hexutil.Uint64
count hexutil.Uint64 count hexutil.Uint64
@ -1512,11 +1635,13 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
want: engine.TooLargeRequest, want: engine.TooLargeRequest,
}, },
} }
for i, tc := range tests { for i, tc := range tests {
result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count) result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count)
if err == nil { if err == nil {
t.Fatalf("test %d: expected error, got %v", i, result) t.Fatalf("test %d: expected error, got %v", i, result)
} }
if have, want := err.Error(), tc.want.Error(); have != want { if have, want := err.Error(), tc.want.Error(); have != want {
t.Fatalf("test %d: have %s, want %s", i, have, want) t.Fatalf("test %d: have %s, want %s", i, have, want)
} }
@ -1529,14 +1654,17 @@ func equalBody(a *types.Body, b *engine.ExecutionPayloadBodyV1) bool {
} else if a == nil || b == nil { } else if a == nil || b == nil {
return false return false
} }
if len(a.Transactions) != len(b.TransactionData) { if len(a.Transactions) != len(b.TransactionData) {
return false return false
} }
for i, tx := range a.Transactions { for i, tx := range a.Transactions {
data, _ := tx.MarshalBinary() data, _ := tx.MarshalBinary()
if !bytes.Equal(data, b.TransactionData[i]) { if !bytes.Equal(data, b.TransactionData[i]) {
return false return false
} }
} }
return reflect.DeepEqual(a.Withdrawals, b.Withdrawals) return reflect.DeepEqual(a.Withdrawals, b.Withdrawals)
} }

View file

@ -97,10 +97,12 @@ func (q *payloadQueue) has(id engine.PayloadID) bool {
if item == nil { if item == nil {
return false return false
} }
if item.id == id { if item.id == id {
return true return true
} }
} }
return false return false
} }

View file

@ -47,12 +47,14 @@ func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, block *type
closed: make(chan struct{}), closed: make(chan struct{}),
} }
stack.RegisterLifecycle(cl) stack.RegisterLifecycle(cl)
return cl, nil return cl, nil
} }
// Start launches the beacon sync with provided sync target. // Start launches the beacon sync with provided sync target.
func (tester *FullSyncTester) Start() error { func (tester *FullSyncTester) Start() error {
tester.wg.Add(1) tester.wg.Add(1)
go func() { go func() {
defer tester.wg.Done() defer tester.wg.Done()
@ -85,6 +87,7 @@ func (tester *FullSyncTester) Start() error {
} }
} }
}() }()
return nil return nil
} }
@ -93,5 +96,6 @@ func (tester *FullSyncTester) Start() error {
func (tester *FullSyncTester) Stop() error { func (tester *FullSyncTester) Stop() error {
close(tester.closed) close(tester.closed)
tester.wg.Wait() tester.wg.Wait()
return nil return nil
} }

View file

@ -271,6 +271,7 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) {
// until sync errors or is finished. // until sync errors or is finished.
func (d *Downloader) fetchBeaconHeaders(from uint64) error { func (d *Downloader) fetchBeaconHeaders(from uint64) error {
var head *types.Header var head *types.Header
_, tail, _, err := d.skeleton.Bounds() _, tail, _, err := d.skeleton.Bounds()
if err != nil { if err != nil {
return err return err
@ -280,11 +281,13 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
// and it should only happen when there are less than 64 post-merge // and it should only happen when there are less than 64 post-merge
// blocks in the network. // blocks in the network.
var localHeaders []*types.Header var localHeaders []*types.Header
if from < tail.Number.Uint64() { if from < tail.Number.Uint64() {
count := tail.Number.Uint64() - from count := tail.Number.Uint64() - from
if count > uint64(fsMinFullBlocks) { if count > uint64(fsMinFullBlocks) {
return fmt.Errorf("invalid origin (%d) of beacon sync (%d)", from, tail.Number) return fmt.Errorf("invalid origin (%d) of beacon sync (%d)", from, tail.Number)
} }
localHeaders = d.readHeaderRange(tail, int(count)) localHeaders = d.readHeaderRange(tail, int(count))
log.Warn("Retrieved beacon headers from local", "from", from, "count", count) log.Warn("Retrieved beacon headers from local", "from", from, "count", count)
} }
@ -305,6 +308,7 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
number := head.Number.Uint64() - uint64(fsMinFullBlocks) number := head.Number.Uint64() - uint64(fsMinFullBlocks)
log.Warn("Pivot seemingly stale, moving", "old", d.pivotHeader.Number, "new", number) log.Warn("Pivot seemingly stale, moving", "old", d.pivotHeader.Number, "new", number)
if d.pivotHeader = d.skeleton.Header(number); d.pivotHeader == nil { if d.pivotHeader = d.skeleton.Header(number); d.pivotHeader == nil {
if number < tail.Number.Uint64() { if number < tail.Number.Uint64() {
dist := tail.Number.Uint64() - number dist := tail.Number.Uint64() - number
@ -320,6 +324,7 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
if d.pivotHeader == nil { if d.pivotHeader == nil {
log.Error("Pivot header is not found", "number", number) log.Error("Pivot header is not found", "number", number)
d.pivotLock.Unlock() d.pivotLock.Unlock()
return errNoPivotHeader return errNoPivotHeader
} }
// Write out the pivot into the database so a rollback beyond // Write out the pivot into the database so a rollback beyond
@ -350,6 +355,7 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
if header == nil { if header == nil {
return fmt.Errorf("missing beacon header %d", from) return fmt.Errorf("missing beacon header %d", from)
} }
headers = append(headers, header) headers = append(headers, header)
hashes = append(hashes, headers[i].Hash()) hashes = append(hashes, headers[i].Hash())
from++ from++

View file

@ -371,6 +371,7 @@ func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, m
if errors.Is(err, ErrMergeTransition) { if errors.Is(err, ErrMergeTransition) {
return err // This is an expected fault, don't keep printing it in a spin-loop return err // This is an expected fault, don't keep printing it in a spin-loop
} }
log.Warn("Synchronisation failed, retrying", "err", err) log.Warn("Synchronisation failed, retrying", "err", err)
return err return err
} }
@ -568,6 +569,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *
rawdb.WriteLastPivotNumber(d.stateDB, pivotNumber) rawdb.WriteLastPivotNumber(d.stateDB, pivotNumber)
} }
} }
d.committed.Store(true) d.committed.Store(true)
if mode == SnapSync && pivot.Number.Uint64() != 0 { if mode == SnapSync && pivot.Number.Uint64() != 0 {
d.committed.Store(false) d.committed.Store(false)
@ -1677,6 +1679,7 @@ func (d *Downloader) processSnapSyncContent() error {
if d.chainInsertHook != nil { if d.chainInsertHook != nil {
d.chainInsertHook(results) d.chainInsertHook(results)
} }
d.reportSnapSyncProgress(false) d.reportSnapSyncProgress(false)
// If we haven't downloaded the pivot block yet, check pivot staleness // If we haven't downloaded the pivot block yet, check pivot staleness
@ -1821,6 +1824,7 @@ func (d *Downloader) commitPivotBlock(result *fetchResult) error {
if err := d.blockchain.SnapSyncCommitHead(block.Hash()); err != nil { if err := d.blockchain.SnapSyncCommitHead(block.Hash()); err != nil {
return err return err
} }
d.committed.Store(true) d.committed.Store(true)
return nil return nil
} }
@ -1859,17 +1863,22 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea
current = last current = last
headers []*types.Header headers []*types.Header
) )
for { for {
parent := d.lightchain.GetHeaderByHash(current.ParentHash) parent := d.lightchain.GetHeaderByHash(current.ParentHash)
if parent == nil { if parent == nil {
break // The chain is not continuous, or the chain is exhausted break // The chain is not continuous, or the chain is exhausted
} }
headers = append(headers, parent) headers = append(headers, parent)
if len(headers) >= count { if len(headers) >= count {
break break
} }
current = parent current = parent
} }
return headers return headers
} }
@ -1889,15 +1898,20 @@ func (d *Downloader) reportSnapSyncProgress(force bool) {
bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable) bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable)
receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable) receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable)
) )
syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes) syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes)
if syncedBytes == 0 { if syncedBytes == 0 {
return return
} }
var ( var (
header = d.blockchain.CurrentHeader() header = d.blockchain.CurrentHeader()
block = d.blockchain.CurrentSnapBlock() block = d.blockchain.CurrentSnapBlock()
) )
syncedBlocks := block.Number.Uint64() - d.syncStartBlock syncedBlocks := block.Number.Uint64() - d.syncStartBlock
if syncedBlocks == 0 { if syncedBlocks == 0 {
return return
} }
@ -1907,12 +1921,14 @@ func (d *Downloader) reportSnapSyncProgress(force bool) {
// We're going to cheat for non-merged networks, but that's fine // We're going to cheat for non-merged networks, but that's fine
latest = d.pivotHeader latest = d.pivotHeader
} }
if latest == nil { if latest == nil {
// This should really never happen, but add some defensive code for now. // This should really never happen, but add some defensive code for now.
// TODO(karalabe): Remove it eventually if we don't see it blow. // TODO(karalabe): Remove it eventually if we don't see it blow.
log.Error("Nil latest block in sync progress report") log.Error("Nil latest block in sync progress report")
return return
} }
var ( var (
left = latest.Number.Uint64() - block.Number.Uint64() left = latest.Number.Uint64() - block.Number.Uint64()
eta = time.Since(d.syncStartTime) / time.Duration(syncedBlocks) * time.Duration(left) eta = time.Since(d.syncStartTime) / time.Duration(syncedBlocks) * time.Duration(left)
@ -1922,6 +1938,8 @@ func (d *Downloader) reportSnapSyncProgress(force bool) {
bodies = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(bodyBytes).TerminalString()) bodies = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(bodyBytes).TerminalString())
receipts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(receiptBytes).TerminalString()) receipts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.Number.Uint64()), common.StorageSize(receiptBytes).TerminalString())
) )
log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta)) log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta))
d.syncLogTime = time.Now() d.syncLogTime = time.Now()
} }

View file

@ -69,9 +69,11 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
if err != nil { if err != nil {
panic(err) panic(err)
} }
t.Cleanup(func() { t.Cleanup(func() {
db.Close() db.Close()
}) })
gspec := &core.Genesis{ gspec := &core.Genesis{
Config: params.TestChainConfig, Config: params.TestChainConfig,
Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}}, Alloc: core.GenesisAlloc{testAddress: {Balance: big.NewInt(1000000000000000)}},
@ -440,9 +442,11 @@ func assertOwnChain(t *testing.T, tester *downloadTester, length int) {
if hs := int(tester.chain.CurrentHeader().Number.Uint64()) + 1; hs != headers { if hs := int(tester.chain.CurrentHeader().Number.Uint64()) + 1; hs != headers {
t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers) t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers)
} }
if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != blocks { if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != blocks {
t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks) t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks)
} }
if rs := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1; rs != receipts { if rs := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1; rs != receipts {
t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts) t.Fatalf("synchronised receipts mismatch: have %v, want %v", rs, receipts)
} }
@ -517,6 +521,7 @@ func testThrottling(t *testing.T, protocol uint, mode SyncMode) {
// Wrap the importer to allow stepping // Wrap the importer to allow stepping
var blocked atomic.Uint32 var blocked atomic.Uint32
proceed := make(chan struct{}) proceed := make(chan struct{})
tester.downloader.chainInsertHook = func(results []*fetchResult) { tester.downloader.chainInsertHook = func(results []*fetchResult) {
blocked.Store(uint32(len(results))) blocked.Store(uint32(len(results)))
@ -984,9 +989,11 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
receiptsNeeded++ receiptsNeeded++
} }
} }
if int(bodiesHave.Load()) != bodiesNeeded { if int(bodiesHave.Load()) != bodiesNeeded {
t.Errorf("body retrieval count mismatch: have %v, want %v", bodiesHave.Load(), bodiesNeeded) t.Errorf("body retrieval count mismatch: have %v, want %v", bodiesHave.Load(), bodiesNeeded)
} }
if int(receiptsHave.Load()) != receiptsNeeded { if int(receiptsHave.Load()) != receiptsNeeded {
t.Errorf("receipt retrieval count mismatch: have %v, want %v", receiptsHave.Load(), receiptsNeeded) t.Errorf("receipt retrieval count mismatch: have %v, want %v", receiptsHave.Load(), receiptsNeeded)
} }
@ -1790,6 +1797,7 @@ func testBeaconSync(t *testing.T, protocol uint, mode SyncMode) {
{name: "Beacon sync with long local chain", local: blockCacheMaxItems - 15 - fsMinFullBlocks/2}, {name: "Beacon sync with long local chain", local: blockCacheMaxItems - 15 - fsMinFullBlocks/2},
{name: "Beacon sync with full local chain", local: blockCacheMaxItems - 15 - 1}, {name: "Beacon sync with full local chain", local: blockCacheMaxItems - 15 - 1},
} }
for _, c := range cases { for _, c := range cases {
t.Run(c.name, func(t *testing.T) { t.Run(c.name, func(t *testing.T) {
t.Parallel() t.Parallel()

View file

@ -286,6 +286,7 @@ func (d *Downloader) concurrentFetch(queue typedQueue, beaconMode bool) error {
_, exp := timeouts.Peek() _, exp := timeouts.Peek()
timeout.Reset(time.Until(time.Unix(0, -exp))) timeout.Reset(time.Until(time.Unix(0, -exp)))
} }
delete(ordering, req) delete(ordering, req)
// New timeout potentially set if there are more requests pending, // New timeout potentially set if there are more requests pending,

View file

@ -436,6 +436,7 @@ func (q *queue) ReserveHeaders(p *peerConnection, count int) *fetchRequest {
continue continue
} }
} }
send = from send = from
} }
// Merge all the skipped batches back // Merge all the skipped batches back
@ -783,6 +784,7 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
if uncleListHashes[index] != header.UncleHash { if uncleListHashes[index] != header.UncleHash {
return errInvalidBody return errInvalidBody
} }
if header.WithdrawalsHash == nil { if header.WithdrawalsHash == nil {
// nil hash means that withdrawals should not be present in body // nil hash means that withdrawals should not be present in body
if withdrawalLists[index] != nil { if withdrawalLists[index] != nil {

View file

@ -345,6 +345,7 @@ func XTestDelivery(t *testing.T) {
uncleHashes[i] = types.CalcUncleHash(uncles) uncleHashes[i] = types.CalcUncleHash(uncles)
} }
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
_, err := q.DeliverBodies(peer.id, txset, txsHashes, uncleset, uncleHashes, nil, nil) _, err := q.DeliverBodies(peer.id, txset, txsHashes, uncleset, uncleHashes, nil, nil)
if err != nil { if err != nil {
fmt.Printf("delivered %d bodies %v\n", len(txset), err) fmt.Printf("delivered %d bodies %v\n", len(txset), err)

View file

@ -366,6 +366,7 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
if linked { if linked {
s.filler.resume() s.filler.resume()
} }
defer func() { defer func() {
if filled := s.filler.suspend(); filled != nil { if filled := s.filler.suspend(); filled != nil {
// If something was filled, try to delete stale sync helpers. If // If something was filled, try to delete stale sync helpers. If
@ -1013,14 +1014,16 @@ func (s *skeleton) processResponse(res *headerResponse) (linked bool, merged boo
context = append(context, fmt.Sprintf("stale_next_%d", i+1)) context = append(context, fmt.Sprintf("stale_next_%d", i+1))
context = append(context, s.progress.Subchains[i+1].Next) context = append(context, s.progress.Subchains[i+1].Next)
} }
log.Error("Cleaning spurious beacon sync leftovers", context...) log.Error("Cleaning spurious beacon sync leftovers", context...)
s.progress.Subchains = s.progress.Subchains[:1]
// Note, here we didn't actually delete the headers at all, // Note, here we didn't actually delete the headers at all,
// just the metadata. We could implement a cleanup mechanism, // just the metadata. We could implement a cleanup mechanism,
// but further modifying corrupted state is kind of asking // but further modifying corrupted state is kind of asking
// for it. Unless there's a good enough reason to risk it, // for it. Unless there's a good enough reason to risk it,
// better to live with the small database junk. // better to live with the small database junk.
s.progress.Subchains = s.progress.Subchains[:1]
} }
} }
break break
@ -1116,6 +1119,7 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
end = number // delete until the requested threshold end = number // delete until the requested threshold
batch = s.db.NewBatch() batch = s.db.NewBatch()
) )
s.progress.Subchains[0].Tail = number s.progress.Subchains[0].Tail = number
s.progress.Subchains[0].Next = filled.ParentHash s.progress.Subchains[0].Next = filled.ParentHash
@ -1132,6 +1136,7 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
} }
// Execute the trimming and the potential rewiring of the progress // Execute the trimming and the potential rewiring of the progress
s.saveSyncStatus(batch) s.saveSyncStatus(batch)
for n := start; n < end; n++ { for n := start; n < end; n++ {
// If the batch grew too big, flush it and continue with a new batch. // If the batch grew too big, flush it and continue with a new batch.
// The catch is that the sync metadata needs to reflect the actually // The catch is that the sync metadata needs to reflect the actually
@ -1148,17 +1153,21 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to write beacon trim data", "err", err) log.Crit("Failed to write beacon trim data", "err", err)
} }
batch.Reset() batch.Reset()
s.progress.Subchains[0].Tail = tmpTail s.progress.Subchains[0].Tail = tmpTail
s.progress.Subchains[0].Next = tmpNext s.progress.Subchains[0].Next = tmpNext
s.saveSyncStatus(batch) s.saveSyncStatus(batch)
} }
rawdb.DeleteSkeletonHeader(batch, n) rawdb.DeleteSkeletonHeader(batch, n)
} }
if err := batch.Write(); err != nil { if err := batch.Write(); err != nil {
log.Crit("Failed to write beacon trim data", "err", err) log.Crit("Failed to write beacon trim data", "err", err)
} }
return nil return nil
} }
@ -1187,19 +1196,23 @@ func (s *skeleton) Bounds() (head *types.Header, tail *types.Header, final *type
return nil, nil, nil, err return nil, nil, nil, err
} }
head = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Head) head = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Head)
if head == nil { if head == nil {
return nil, nil, nil, fmt.Errorf("head skeleton header %d is missing", progress.Subchains[0].Head) return nil, nil, nil, fmt.Errorf("head skeleton header %d is missing", progress.Subchains[0].Head)
} }
tail = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Tail) tail = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Tail)
if tail == nil { if tail == nil {
return nil, nil, nil, fmt.Errorf("tail skeleton header %d is missing", progress.Subchains[0].Tail) return nil, nil, nil, fmt.Errorf("tail skeleton header %d is missing", progress.Subchains[0].Tail)
} }
if progress.Finalized != nil && tail.Number.Uint64() <= *progress.Finalized && *progress.Finalized <= head.Number.Uint64() { if progress.Finalized != nil && tail.Number.Uint64() <= *progress.Finalized && *progress.Finalized <= head.Number.Uint64() {
final = rawdb.ReadSkeletonHeader(s.db, *progress.Finalized) final = rawdb.ReadSkeletonHeader(s.db, *progress.Finalized)
if final == nil { if final == nil {
return nil, nil, nil, fmt.Errorf("finalized skeleton header %d is missing", *progress.Finalized) return nil, nil, nil, fmt.Errorf("finalized skeleton header %d is missing", *progress.Finalized)
} }
} }
return head, tail, final, nil return head, tail, final, nil
} }

View file

@ -58,6 +58,7 @@ func (hf *hookedBackfiller) suspend() *types.Header {
if hf.suspendHook != nil { if hf.suspendHook != nil {
return hf.suspendHook() return hf.suspendHook()
} }
return nil // we don't really care about header cleanups for now return nil // we don't really care about header cleanups for now
} }
@ -161,6 +162,7 @@ func (p *skeletonTestPeer) RequestHeadersByNumber(origin uint64, amount int, ski
} }
} }
} }
p.served.Add(uint64(len(headers))) p.served.Add(uint64(len(headers)))
hashes := make([]common.Hash, len(headers)) hashes := make([]common.Hash, len(headers))
@ -487,6 +489,7 @@ func TestSkeletonSyncExtend(t *testing.T) {
skeleton.Sync(tt.head, nil, true) skeleton.Sync(tt.head, nil, true)
<-wait <-wait
if err := skeleton.Sync(tt.extend, nil, false); err != tt.err { if err := skeleton.Sync(tt.extend, nil, false); err != tt.err {
t.Errorf("test %d: extension failure mismatch: have %v, want %v", i, err, tt.err) t.Errorf("test %d: extension failure mismatch: have %v, want %v", i, err, tt.err)
} }
@ -530,6 +533,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
for i := 0; i < len(chain)/2; i++ { // Fork at block #5000 for i := 0; i < len(chain)/2; i++ { // Fork at block #5000
sidechain = append(sidechain, chain[i]) sidechain = append(sidechain, chain[i])
} }
for i := len(chain) / 2; i < len(chain); i++ { for i := len(chain) / 2; i < len(chain); i++ {
sidechain = append(sidechain, &types.Header{ sidechain = append(sidechain, &types.Header{
ParentHash: sidechain[i-1].Hash(), ParentHash: sidechain[i-1].Hash(),
@ -824,6 +828,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
} }
// Create a backfiller if we need to run more advanced tests // Create a backfiller if we need to run more advanced tests
filler := newHookedBackfiller() filler := newHookedBackfiller()
if tt.fill { if tt.fill {
var filled *types.Header var filled *types.Header
@ -892,18 +897,23 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
t.Error(err) t.Error(err)
continue continue
} }
if !tt.unpredictable { if !tt.unpredictable {
var served uint64 var served uint64
for _, peer := range tt.peers { for _, peer := range tt.peers {
served += peer.served.Load() served += peer.served.Load()
} }
if served != tt.midserve { if served != tt.midserve {
t.Errorf("test %d, mid state: served headers mismatch: have %d, want %d", i, served, tt.midserve) t.Errorf("test %d, mid state: served headers mismatch: have %d, want %d", i, served, tt.midserve)
} }
var drops uint64 var drops uint64
for _, peer := range tt.peers { for _, peer := range tt.peers {
drops += peer.dropped.Load() drops += peer.dropped.Load()
} }
if drops != tt.middrop { if drops != tt.middrop {
t.Errorf("test %d, mid state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop) t.Errorf("test %d, mid state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop)
} }
@ -934,6 +944,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
return nil return nil
} }
waitStart = time.Now() waitStart = time.Now()
for waitTime := 20 * time.Millisecond; time.Since(waitStart) < 2*time.Second; waitTime = waitTime * 2 { for waitTime := 20 * time.Millisecond; time.Since(waitStart) < 2*time.Second; waitTime = waitTime * 2 {
time.Sleep(waitTime) time.Sleep(waitTime)
// Check the post-init end state if it matches the required results // Check the post-init end state if it matches the required results
@ -952,19 +963,25 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
for _, peer := range tt.peers { for _, peer := range tt.peers {
served += peer.served.Load() served += peer.served.Load()
} }
if tt.newPeer != nil { if tt.newPeer != nil {
served += tt.newPeer.served.Load() served += tt.newPeer.served.Load()
} }
if served != tt.endserve { if served != tt.endserve {
t.Errorf("test %d, end state: served headers mismatch: have %d, want %d", i, served, tt.endserve) t.Errorf("test %d, end state: served headers mismatch: have %d, want %d", i, served, tt.endserve)
} }
drops := uint64(0) drops := uint64(0)
for _, peer := range tt.peers { for _, peer := range tt.peers {
drops += peer.dropped.Load() drops += peer.dropped.Load()
} }
if tt.newPeer != nil { if tt.newPeer != nil {
drops += tt.newPeer.dropped.Load() drops += tt.newPeer.dropped.Load()
} }
if drops != tt.enddrop { if drops != tt.enddrop {
t.Errorf("test %d, end state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop) t.Errorf("test %d, end state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop)
} }

View file

@ -163,7 +163,10 @@ func newHandler(config *handlerConfig) (*handler, error) {
// time. But we don't have any recent state for full sync. // time. But we don't have any recent state for full sync.
// In these cases however it's safe to reenable snap sync. // In these cases however it's safe to reenable snap sync.
fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock() fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock()
if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 { if fullBlock.Number.Uint64() == 0 && snapBlock.Number.Uint64() > 0 {
log.Warn("Preventing switching sync mode from full sync to snap sync")
// Note: Ideally this should never happen with bor, but to be extra // Note: Ideally this should never happen with bor, but to be extra
// preventive we won't allow it to roll over to snap sync until // preventive we won't allow it to roll over to snap sync until
// we have it working // we have it working
@ -171,8 +174,6 @@ func newHandler(config *handlerConfig) (*handler, error) {
// TODO(snap): Uncomment when we have snap sync working // TODO(snap): Uncomment when we have snap sync working
// h.snapSync = uint32(1) // h.snapSync = uint32(1)
// log.Warn("Switch sync mode from full sync to snap sync") // log.Warn("Switch sync mode from full sync to snap sync")
log.Warn("Preventing switching sync mode from full sync to snap sync")
} }
} else { } else {
if h.chain.CurrentBlock().Number.Uint64() > 0 { if h.chain.CurrentBlock().Number.Uint64() > 0 {
@ -348,6 +349,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
number = head.Number.Uint64() number = head.Number.Uint64()
td = h.chain.GetTd(hash, number) td = h.chain.GetTd(hash, number)
) )
forkID := forkid.NewID(h.chain.Config(), genesis.Hash(), number, head.Time) forkID := forkid.NewID(h.chain.Config(), genesis.Hash(), number, head.Time)
if err := peer.Handshake(h.networkID, td, hash, genesis.Hash(), forkID, h.forkFilter); err != nil { if err := peer.Handshake(h.networkID, td, hash, genesis.Hash(), forkID, h.forkFilter); err != nil {
peer.Log().Debug("Ethereum handshake failed", "err", err) peer.Log().Debug("Ethereum handshake failed", "err", err)
@ -464,6 +466,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
if err != nil { if err != nil {
return err return err
} }
go func(number uint64, hash common.Hash, req *eth.Request) { go func(number uint64, hash common.Hash, req *eth.Request) {
// Ensure the request gets cancelled in case of error/drop // Ensure the request gets cancelled in case of error/drop
defer req.Close() defer req.Close()

View file

@ -697,6 +697,7 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
} }
// Initiate a block propagation across the peers // Initiate a block propagation across the peers
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
header := source.chain.CurrentBlock() header := source.chain.CurrentBlock()
source.handler.BroadcastBlock(source.chain.GetBlock(header.Hash(), header.Number.Uint64()), true) source.handler.BroadcastBlock(source.chain.GetBlock(header.Hash(), header.Number.Uint64()), true)
@ -784,8 +785,10 @@ func testBroadcastMalformedBlock(t *testing.T, protocol uint) {
malformedUncles := head malformedUncles := head
malformedUncles.UncleHash[0]++ malformedUncles.UncleHash[0]++
malformedTransactions := head malformedTransactions := head
malformedTransactions.TxHash[0]++ malformedTransactions.TxHash[0]++
malformedEverything := head malformedEverything := head
malformedEverything.UncleHash[0]++ malformedEverything.UncleHash[0]++
malformedEverything.TxHash[0]++ malformedEverything.TxHash[0]++

View file

@ -230,6 +230,7 @@ func handleMessage(backend Backend, peer *Peer) error {
if peer.Version() == ETH67 { if peer.Version() == ETH67 {
handlers = eth67 handlers = eth67
} }
if peer.Version() >= ETH68 { if peer.Version() >= ETH68 {
handlers = eth68 handlers = eth68
} }

View file

@ -111,9 +111,11 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
if _, err := chain.InsertChain(bs); err != nil { if _, err := chain.InsertChain(bs); err != nil {
panic(err) panic(err)
} }
for _, block := range bs { for _, block := range bs {
chain.StateCache().TrieDB().Commit(block.Root(), false) chain.StateCache().TrieDB().Commit(block.Root(), false)
} }
txconfig := txpool.DefaultConfig txconfig := txpool.DefaultConfig
txconfig.Journal = "" // Don't litter the disk with test journals txconfig.Journal = "" // Don't litter the disk with test journals
@ -430,6 +432,7 @@ func testGetBlockBodies(t *testing.T, protocol uint) {
hashes = append(hashes, hash) hashes = append(hashes, hash)
if tt.available[j] && len(bodies) < tt.expected { if tt.available[j] && len(bodies) < tt.expected {
block := backend.chain.GetBlockByHash(hash) block := backend.chain.GetBlockByHash(hash)
bodies = append(bodies, &BlockBody{Transactions: block.Transactions(), Uncles: block.Uncles(), Withdrawals: block.Withdrawals()}) bodies = append(bodies, &BlockBody{Transactions: block.Transactions(), Uncles: block.Uncles(), Withdrawals: block.Withdrawals()})
} }
} }
@ -524,6 +527,7 @@ func testGetNodeData(t *testing.T, protocol uint, drop bool) {
GetNodeDataPacket: hashes, GetNodeDataPacket: hashes,
}) })
msg, err := peer.app.ReadMsg() msg, err := peer.app.ReadMsg()
if !drop { if !drop {
if err != nil { if err != nil {
t.Fatalf("failed to read node data response: %v", err) t.Fatalf("failed to read node data response: %v", err)
@ -558,6 +562,7 @@ func testGetNodeData(t *testing.T, protocol uint, drop bool) {
// Sanity check whether all state matches. // Sanity check whether all state matches.
accounts := []common.Address{testAddr, acc1Addr, acc2Addr} accounts := []common.Address{testAddr, acc1Addr, acc2Addr}
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
root := backend.chain.GetBlockByNumber(i).Root() root := backend.chain.GetBlockByNumber(i).Root()
reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil) reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil)
@ -640,6 +645,7 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
hashes []common.Hash hashes []common.Hash
receipts [][]*types.Receipt receipts [][]*types.Receipt
) )
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ { for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
block := backend.chain.GetBlockByNumber(i) block := backend.chain.GetBlockByNumber(i)

View file

@ -387,10 +387,12 @@ func handleBlockBodies66(backend Backend, msg Decoder, peer *Peer) error {
for i, body := range res.BlockBodiesPacket { for i, body := range res.BlockBodiesPacket {
txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher) txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher)
uncleHashes[i] = types.CalcUncleHash(body.Uncles) uncleHashes[i] = types.CalcUncleHash(body.Uncles)
if body.Withdrawals != nil { if body.Withdrawals != nil {
withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher) withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher)
} }
} }
return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes} return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes}
} }
return peer.dispatchResponse(&Response{ return peer.dispatchResponse(&Response{
@ -440,6 +442,7 @@ func handleNewPooledTransactionHashes66(backend Backend, msg Decoder, peer *Peer
if !backend.AcceptTxs() { if !backend.AcceptTxs() {
return nil return nil
} }
ann := new(NewPooledTransactionHashesPacket66) ann := new(NewPooledTransactionHashesPacket66)
if err := msg.Decode(ann); err != nil { if err := msg.Decode(ann); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
@ -457,10 +460,13 @@ func handleNewPooledTransactionHashes68(backend Backend, msg Decoder, peer *Peer
if !backend.AcceptTxs() { if !backend.AcceptTxs() {
return nil return nil
} }
ann := new(NewPooledTransactionHashesPacket68) ann := new(NewPooledTransactionHashesPacket68)
if err := msg.Decode(ann); err != nil { if err := msg.Decode(ann); err != nil {
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
} }
if len(ann.Hashes) != len(ann.Types) || len(ann.Hashes) != len(ann.Sizes) { if len(ann.Hashes) != len(ann.Types) || len(ann.Hashes) != len(ann.Sizes) {
return fmt.Errorf("%w: message %v: invalid len of fields: %v %v %v", errDecode, msg, len(ann.Hashes), len(ann.Types), len(ann.Sizes)) return fmt.Errorf("%w: message %v: invalid len of fields: %v %v %v", errDecode, msg, len(ann.Hashes), len(ann.Types), len(ann.Sizes))
} }
@ -468,6 +474,7 @@ func handleNewPooledTransactionHashes68(backend Backend, msg Decoder, peer *Peer
for _, hash := range ann.Hashes { for _, hash := range ann.Hashes {
peer.markTransaction(hash) peer.markTransaction(hash)
} }
return backend.Handle(peer, ann) return backend.Handle(peer, ann)
} }

View file

@ -254,6 +254,7 @@ func (p *BlockBodiesPacket) Unpack() ([][]*types.Transaction, [][]*types.Header,
for i, body := range *p { for i, body := range *p {
txset[i], uncleset[i], withdrawalset[i] = body.Transactions, body.Uncles, body.Withdrawals txset[i], uncleset[i], withdrawalset[i] = body.Transactions, body.Uncles, body.Withdrawals
} }
return txset, uncleset, withdrawalset return txset, uncleset, withdrawalset
} }

View file

@ -1510,6 +1510,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
trie, _ := trie.New(id, db) trie, _ := trie.New(id, db)
storageTries[common.BytesToHash(key)] = trie storageTries[common.BytesToHash(key)] = trie
} }
return db.Scheme(), accTrie, entries, storageTries, storageEntries return db.Scheme(), accTrie, entries, storageTries, storageEntries
} }
@ -1537,6 +1538,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
stNodes *trie.NodeSet stNodes *trie.NodeSet
stEntries entrySlice stEntries entrySlice
) )
if boundary { if boundary {
stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db) stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db)
} else { } else {
@ -1572,15 +1574,19 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
if err != nil { if err != nil {
panic(err) panic(err)
} }
for i := uint64(1); i <= uint64(accounts); i++ { for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i) key := key32(i)
id := trie.StorageTrieID(root, common.BytesToHash(key), storageRoots[common.BytesToHash(key)]) id := trie.StorageTrieID(root, common.BytesToHash(key), storageRoots[common.BytesToHash(key)])
trie, err := trie.New(id, db) trie, err := trie.New(id, db)
if err != nil { if err != nil {
panic(err) panic(err)
} }
storageTries[common.BytesToHash(key)] = trie storageTries[common.BytesToHash(key)] = trie
} }
return db.Scheme(), accTrie, entries, storageTries, storageEntries return db.Scheme(), accTrie, entries, storageTries, storageEntries
} }
@ -1603,7 +1609,9 @@ func makeStorageTrieWithSeed(owner common.Hash, n, seed uint64, db *trie.Databas
entries = append(entries, elem) entries = append(entries, elem)
} }
sort.Sort(entries) sort.Sort(entries)
root, nodes := trie.Commit(false) root, nodes := trie.Commit(false)
return root, nodes, entries return root, nodes, entries
} }
@ -1654,12 +1662,15 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
entries = append(entries, elem) entries = append(entries, elem)
} }
sort.Sort(entries) sort.Sort(entries)
root, nodes := trie.Commit(false) root, nodes := trie.Commit(false)
return root, nodes, entries return root, nodes, entries
} }
func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) { func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
t.Helper() t.Helper()
triedb := trie.NewDatabase(rawdb.NewDatabase(db)) triedb := trie.NewDatabase(rawdb.NewDatabase(db))
accTrie, err := trie.New(trie.StateTrieID(root), triedb) accTrie, err := trie.New(trie.StateTrieID(root), triedb)
if err != nil { if err != nil {
@ -1678,6 +1689,7 @@ func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
log.Crit("Invalid account encountered during snapshot creation", "err", err) log.Crit("Invalid account encountered during snapshot creation", "err", err)
} }
accounts++ accounts++
if acc.Root != types.EmptyRootHash { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root) id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root)
storeTrie, err := trie.NewStateTrie(id, triedb) storeTrie, err := trie.NewStateTrie(id, triedb)
@ -1716,6 +1728,7 @@ func TestSyncAccountPerformance(t *testing.T) {
}) })
} }
) )
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100) nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
mkSource := func(name string) *testPeer { mkSource := func(name string) *testPeer {

View file

@ -72,6 +72,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe
// function to deref it. // function to deref it.
if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil { if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil {
statedb.Database().TrieDB().Reference(block.Root(), common.Hash{}) statedb.Database().TrieDB().Reference(block.Root(), common.Hash{})
return statedb, func() { return statedb, func() {
statedb.Database().TrieDB().Dereference(block.Root()) statedb.Database().TrieDB().Dereference(block.Root())
}, nil }, nil
@ -188,6 +189,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe
nodes, imgs := database.TrieDB().Size() nodes, imgs := database.TrieDB().Size()
log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs) log.Info("Historical state regenerated", "block", current.NumberU64(), "elapsed", time.Since(start), "nodes", nodes, "preimages", imgs)
} }
return statedb, func() { database.TrieDB().Dereference(block.Root()) }, nil return statedb, func() { database.TrieDB().Dereference(block.Root()) }, nil
} }
@ -224,6 +226,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
// Not yet the searched for transaction, execute on top of the current state // Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{}) vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{})
statedb.SetTxContext(tx.Hash(), idx) statedb.SetTxContext(tx.Hash(), idx)
// nolint : contextcheck
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()), nil); err != nil { if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas()), nil); err != nil {
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction %#x failed: %v", tx.Hash(), err)
} }
@ -231,5 +234,6 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect // Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number())) statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
} }
return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash()) return nil, vm.BlockContext{}, nil, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
} }

View file

@ -286,6 +286,7 @@ func (h *handler) doSync(op *chainSyncOp) error {
atomic.StoreUint32(&h.acceptTxs, 1) atomic.StoreUint32(&h.acceptTxs, 1)
} }
} }
if head.Number.Uint64() > 0 { if head.Number.Uint64() > 0 {
// We've completed a sync cycle, notify all peers of new state. This path is // We've completed a sync cycle, notify all peers of new state. This path is
// essential in star-topology networks where a gateway node needs to notify // essential in star-topology networks where a gateway node needs to notify

View file

@ -288,15 +288,18 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
if !supported { if !supported {
return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
} }
sub := notifier.CreateSubscription() sub := notifier.CreateSubscription()
// nolint : contextcheck // nolint : contextcheck
resCh := api.traceChain(from, to, config, notifier.Closed()) resCh := api.traceChain(from, to, config, notifier.Closed())
go func() { go func() {
for result := range resCh { for result := range resCh {
notifier.Notify(sub.ID, result) notifier.Notify(sub.ID, result)
} }
}() }()
return sub, nil return sub, nil
} }
@ -350,6 +353,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
txs = txs[:len(txs)-1] txs = txs[:len(txs)-1]
stateSyncPresent = false stateSyncPresent = false
} }
for i, tx := range task.block.Transactions() { for i, tx := range task.block.Transactions() {
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee()) msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
txctx := &Context{ txctx := &Context{
@ -421,6 +425,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
default: default:
log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin)) log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin))
} }
close(resCh) close(resCh)
}() }()
// Feed all the blocks both into the tracer, as well as fast process concurrently // Feed all the blocks both into the tracer, as well as fast process concurrently
@ -442,6 +447,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
failed = err failed = err
break break
} }
next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1)) next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1))
if err != nil { if err != nil {
failed = err failed = err
@ -460,10 +466,12 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
// limit, the trie database will be reconstructed from scratch only // limit, the trie database will be reconstructed from scratch only
// if the relevant state is available in disk. // if the relevant state is available in disk.
var preferDisk bool var preferDisk bool
if statedb != nil { if statedb != nil {
s1, s2 := statedb.Database().TrieDB().Size() s1, s2 := statedb.Database().TrieDB().Size()
preferDisk = s1+s2 > defaultTracechainMemLimit preferDisk = s1+s2 > defaultTracechainMemLimit
} }
statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk) statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk)
if err != nil { if err != nil {
failed = err failed = err
@ -495,6 +503,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
next = start.NumberU64() + 1 next = start.NumberU64() + 1
done = make(map[uint64]*blockTraceResult) done = make(map[uint64]*blockTraceResult)
) )
for res := range resCh { for res := range resCh {
// Queue up next received result // Queue up next received result
result := &blockTraceResult{ result := &blockTraceResult{
@ -518,6 +527,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
} }
} }
}() }()
return retCh return retCh
} }
@ -636,10 +646,12 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
if config != nil && config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer release() defer release()
var ( var (
@ -660,6 +672,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
txContext = core.NewEVMTxContext(msg) txContext = core.NewEVMTxContext(msg)
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{}) vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
) )
statedb.SetTxContext(tx.Hash(), i) statedb.SetTxContext(tx.Hash(), i)
//nolint: nestif //nolint: nestif
if stateSyncPresent && i == len(txs)-1 { if stateSyncPresent && i == len(txs)-1 {
@ -758,6 +771,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer release() defer release()
// create and add empty mvHashMap in statedb as StateAtBlock does not have mvHashmap in it. // create and add empty mvHashMap in statedb as StateAtBlock does not have mvHashmap in it.
@ -778,6 +792,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
if threads > len(txs) { if threads > len(txs) {
threads = len(txs) threads = len(txs)
} }
jobs := make(chan *txTraceTask, threads) jobs := make(chan *txTraceTask, threads)
for th := 0; th < threads; th++ { for th := 0; th < threads; th++ {
pend.Add(1) pend.Add(1)
@ -982,10 +997,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
if config != nil && config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false) statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer release() defer release()
// Retrieve the tracing configurations, or use default values // Retrieve the tracing configurations, or use default values
@ -1040,6 +1057,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
if !canon { if !canon {
prefix = fmt.Sprintf("%valt-", prefix) prefix = fmt.Sprintf("%valt-", prefix)
} }
dump, err = os.CreateTemp(os.TempDir(), prefix) dump, err = os.CreateTemp(os.TempDir(), prefix)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1143,10 +1161,12 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
if err != nil { if err != nil {
return nil, err return nil, err
} }
msg, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec) msg, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer release() defer release()
txctx := &Context{ txctx := &Context{
@ -1190,18 +1210,22 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
if config != nil && config.Reexec != nil { if config != nil && config.Reexec != nil {
reexec = *config.Reexec reexec = *config.Reexec
} }
statedb, release, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true, false) statedb, release, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer release() defer release()
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil) vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
// Apply the customization rules if required. // Apply the customization rules if required.
if config != nil { if config != nil {
if err := config.StateOverrides.Apply(statedb); err != nil { if err := config.StateOverrides.Apply(statedb); err != nil {
return nil, err return nil, err
} }
config.BlockOverrides.Apply(&vmctx) config.BlockOverrides.Apply(&vmctx)
} }
// Execute the trace // Execute the trace
@ -1238,6 +1262,7 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
timeout = defaultTraceTimeout timeout = defaultTraceTimeout
txContext = core.NewEVMTxContext(message) txContext = core.NewEVMTxContext(message)
) )
if config == nil { if config == nil {
config = &TraceConfig{} config = &TraceConfig{}
} }
@ -1249,6 +1274,7 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
return nil, err return nil, err
} }
} }
vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true}) vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true})
// Define a meaningful timeout of a single transaction trace // Define a meaningful timeout of a single transaction trace
@ -1257,15 +1283,19 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
return nil, err return nil, err
} }
} }
deadlineCtx, cancel := context.WithTimeout(ctx, timeout) deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
go func() { go func() {
<-deadlineCtx.Done() <-deadlineCtx.Done()
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) { if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
tracer.Stop(errors.New("execution timeout")) tracer.Stop(errors.New("execution timeout"))
// Stop evm execution. Note cancellation is not necessarily immediate. // Stop evm execution. Note cancellation is not necessarily immediate.
vmenv.Cancel() vmenv.Cancel()
} }
}() }()
defer cancel() defer cancel()
// Call Prepare to clear out the statedb access list // Call Prepare to clear out the statedb access list
@ -1287,6 +1317,7 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
return nil, fmt.Errorf("tracing failed: %w", err) return nil, fmt.Errorf("tracing failed: %w", err)
} }
} }
return tracer.GetResult() return tracer.GetResult()
} }
@ -1314,30 +1345,37 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig)
chainConfigCopy.BerlinBlock = block chainConfigCopy.BerlinBlock = block
canon = false canon = false
} }
if block := override.LondonBlock; block != nil { if block := override.LondonBlock; block != nil {
chainConfigCopy.LondonBlock = block chainConfigCopy.LondonBlock = block
canon = false canon = false
} }
if block := override.ArrowGlacierBlock; block != nil { if block := override.ArrowGlacierBlock; block != nil {
chainConfigCopy.ArrowGlacierBlock = block chainConfigCopy.ArrowGlacierBlock = block
canon = false canon = false
} }
if block := override.GrayGlacierBlock; block != nil { if block := override.GrayGlacierBlock; block != nil {
chainConfigCopy.GrayGlacierBlock = block chainConfigCopy.GrayGlacierBlock = block
canon = false canon = false
} }
if block := override.MergeNetsplitBlock; block != nil { if block := override.MergeNetsplitBlock; block != nil {
chainConfigCopy.MergeNetsplitBlock = block chainConfigCopy.MergeNetsplitBlock = block
canon = false canon = false
} }
if timestamp := override.ShanghaiTime; timestamp != nil { if timestamp := override.ShanghaiTime; timestamp != nil {
chainConfigCopy.ShanghaiTime = timestamp chainConfigCopy.ShanghaiTime = timestamp
canon = false canon = false
} }
if timestamp := override.CancunTime; timestamp != nil { if timestamp := override.CancunTime; timestamp != nil {
chainConfigCopy.CancunTime = timestamp chainConfigCopy.CancunTime = timestamp
canon = false canon = false
} }
if timestamp := override.PragueTime; timestamp != nil { if timestamp := override.PragueTime; timestamp != nil {
chainConfigCopy.PragueTime = timestamp chainConfigCopy.PragueTime = timestamp
canon = false canon = false

View file

@ -66,6 +66,7 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer release() defer release()
// Execute all the transaction contained within the block concurrently // Execute all the transaction contained within the block concurrently

Some files were not shown because too many files have changed in this diff Show more