mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
dev: fix: some wsl lint issues
This commit is contained in:
parent
2c87219c80
commit
3af5e435c7
145 changed files with 1488 additions and 15 deletions
|
|
@ -124,6 +124,7 @@ func (b *SimulatedBackend) Commit() common.Hash {
|
|||
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
|
||||
}
|
||||
|
||||
blockHash := b.pendingBlock.Hash()
|
||||
|
||||
// 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)
|
||||
vmEnv := vm.NewEVM(evmContext, txContext, stateDB, b.config, vm.Config{NoBaseFee: true})
|
||||
gasPool := new(core.GasPool).AddGas(math.MaxUint64)
|
||||
|
||||
//nolint:contextcheck
|
||||
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 {
|
||||
return body, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("block body not found")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1349,6 +1349,7 @@ func TestCommitReturnValue(t *testing.T) {
|
|||
|
||||
testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||
sim := simTestBackend(testAddr)
|
||||
|
||||
defer sim.Close()
|
||||
|
||||
startBlockHeight := sim.blockchain.CurrentBlock().Number.Uint64()
|
||||
|
|
@ -1380,6 +1381,7 @@ func TestCommitReturnValue(t *testing.T) {
|
|||
if h2 == h2fork {
|
||||
t.Error("The block in the fork and the original block are the same block!")
|
||||
}
|
||||
|
||||
if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil {
|
||||
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)
|
||||
sim := simTestBackend(testAddr)
|
||||
|
||||
defer sim.Close()
|
||||
|
||||
sim.Commit() // h1
|
||||
|
|
|
|||
|
|
@ -199,9 +199,11 @@ func TestUnpackAnonymousLogIntoMap(t *testing.T) {
|
|||
|
||||
var received map[string]interface{}
|
||||
err := bc.UnpackLogIntoMap(received, "received", mockLog)
|
||||
|
||||
if err == nil {
|
||||
t.Error("unpacking anonymous event is not supported")
|
||||
}
|
||||
|
||||
if err.Error() != "no event signature" {
|
||||
t.Errorf("expected error 'no event signature', got '%s'", err)
|
||||
}
|
||||
|
|
@ -384,6 +386,7 @@ func TestCall(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
var method, methodWithArg = "something", "somethingArrrrg"
|
||||
|
||||
tests := []struct {
|
||||
name, method string
|
||||
opts *bind.CallOpts
|
||||
|
|
@ -482,6 +485,7 @@ func TestCall(t *testing.T) {
|
|||
results: &[]interface{}{0},
|
||||
wantErr: true,
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
bc := bind.NewBoundContract(common.HexToAddress("0x0"), abi.ABI{
|
||||
Methods: map[string]abi.Method{
|
||||
|
|
@ -496,15 +500,19 @@ func TestCall(t *testing.T) {
|
|||
},
|
||||
}, test.mc, nil, nil)
|
||||
err := bc.Call(test.opts, test.results, test.method)
|
||||
|
||||
if test.wantErr || test.wantErrExact != nil {
|
||||
if err == nil {
|
||||
t.Fatalf("%q expected error", test.name)
|
||||
}
|
||||
|
||||
if test.wantErrExact != nil && !errors.Is(err, test.wantErrExact) {
|
||||
t.Fatalf("%q expected error %q but got %q", test.name, test.wantErrExact, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("%q unexpected error: %v", test.name, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ func abigen(c *cli.Context) error {
|
|||
utils.Fatalf("No destination package specified (--pkg)")
|
||||
}
|
||||
var lang bind.Lang
|
||||
|
||||
switch c.String(langFlag.Name) {
|
||||
case "go":
|
||||
lang = bind.LangGo
|
||||
|
|
@ -120,6 +121,7 @@ func abigen(c *cli.Context) error {
|
|||
abi []byte
|
||||
err error
|
||||
)
|
||||
|
||||
input := c.String(abiFlag.Name)
|
||||
if input == "-" {
|
||||
abi, err = io.ReadAll(os.Stdin)
|
||||
|
|
@ -132,6 +134,7 @@ func abigen(c *cli.Context) error {
|
|||
abis = append(abis, string(abi))
|
||||
|
||||
var bin []byte
|
||||
|
||||
if binFile := c.String(binFlag.Name); binFile != "" {
|
||||
if bin, err = os.ReadFile(binFile); err != nil {
|
||||
utils.Fatalf("Failed to read input bytecode: %v", err)
|
||||
|
|
@ -225,6 +228,7 @@ func abigen(c *cli.Context) error {
|
|||
fmt.Printf("%s\n", code)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := os.WriteFile(c.String(outFlag.Name), []byte(code), 0600); err != nil {
|
||||
utils.Fatalf("Failed to write ABI binding: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ func newNameFilter(patterns ...string) (*nameFilter, error) {
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +41,9 @@ func (f *nameFilter) add(pattern string) error {
|
|||
f.files[file] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
f.fulls[pattern] = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ func getCheckpoint(ctx *cli.Context, client *rpc.Client) *params.TrustedCheckpoi
|
|||
|
||||
if ctx.IsSet(indexFlag.Name) {
|
||||
var result [3]string
|
||||
|
||||
index := uint64(ctx.Int64(indexFlag.Name))
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -329,6 +329,7 @@ func initializeSecrets(c *cli.Context) error {
|
|||
return fmt.Errorf("failed to read enough random")
|
||||
}
|
||||
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||
|
||||
if c.Bool(utils.LightKDFFlag.Name) {
|
||||
n, p = keystore.LightScryptN, keystore.LightScryptP
|
||||
}
|
||||
|
|
@ -385,6 +386,7 @@ func attestFile(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
utils.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
configDir := ctx.String(configdirFlag.Name)
|
||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||
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 {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
ui = core.NewCommandlineUI()
|
||||
pwStorage storage.Storage = &storage.NoStorage{}
|
||||
ksLoc = c.String(keystoreFlag.Name)
|
||||
lightKdf = c.Bool(utils.LightKDFFlag.Name)
|
||||
)
|
||||
|
||||
am := core.StartClefAccountManager(ksLoc, true, lightKdf, "")
|
||||
api := core.NewSignerAPI(am, 0, true, ui, nil, false, pwStorage)
|
||||
internalApi := core.NewUIServerAPI(api)
|
||||
|
||||
return internalApi, ui, nil
|
||||
}
|
||||
|
||||
|
|
@ -432,6 +437,7 @@ func setCredential(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
utils.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
configDir := ctx.String(configdirFlag.Name)
|
||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
||||
|
|
@ -460,6 +466,7 @@ func removeCredential(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
utils.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
configDir := ctx.String(configdirFlag.Name)
|
||||
vaultLocation := filepath.Join(configDir, common.Bytes2Hex(crypto.Keccak256([]byte("vault"), stretchedKey)[:10]))
|
||||
pwkey := crypto.Keccak256([]byte("credentials"), stretchedKey)
|
||||
|
|
@ -501,10 +508,13 @@ func newAccount(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr, err := internalApi.New(context.Background())
|
||||
|
||||
if err == nil {
|
||||
fmt.Printf("Generated account %v\n", addr.String())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -513,17 +523,23 @@ func listAccounts(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
accs, err := internalApi.ListAccounts(context.Background())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(accs) == 0 {
|
||||
fmt.Println("\nThe keystore is empty.")
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
for _, account := range accs {
|
||||
fmt.Printf("%v (%v)\n", account.Address, account.URL)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -532,18 +548,25 @@ func listWallets(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
wallets := internalApi.ListWallets()
|
||||
|
||||
if len(wallets) == 0 {
|
||||
fmt.Println("\nThere are no wallets.")
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
for i, wallet := range wallets {
|
||||
fmt.Printf("- Wallet %d at %v (%v %v)\n", i, wallet.URL, wallet.Status, wallet.Failure)
|
||||
|
||||
for j, acc := range wallet.Accounts {
|
||||
fmt.Printf(" -Account %d: %v (%v)\n", j, acc.Address, acc.URL)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -552,14 +575,19 @@ func accountImport(c *cli.Context) error {
|
|||
if c.Args().Len() != 1 {
|
||||
return errors.New("<keyfile> must be given as first argument.")
|
||||
}
|
||||
|
||||
internalApi, ui, err := initInternalApi(c)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pKey, err := crypto.LoadECDSA(c.Args().First())
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
readPw := func(prompt string) (string, error) {
|
||||
resp, err := ui.OnInputRequired(core.UserInputRequest{
|
||||
Title: "Password",
|
||||
|
|
@ -569,23 +597,31 @@ func accountImport(c *cli.Context) error {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return resp.Text, nil
|
||||
}
|
||||
first, err := readPw("Please enter a password for the imported account")
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
second, err := readPw("Please repeat the password you just entered")
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if first != second {
|
||||
return errors.New("Passwords do not match")
|
||||
}
|
||||
|
||||
acc, err := internalApi.ImportRawKey(hex.EncodeToString(crypto.FromECDSA(pKey)), first)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ui.ShowInfo(fmt.Sprintf(`Key imported:
|
||||
Address %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.`,
|
||||
acc.Address, acc.URL.Path))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -630,6 +667,7 @@ func signer(c *cli.Context) error {
|
|||
var (
|
||||
ui core.UIClientAPI
|
||||
)
|
||||
|
||||
if c.Bool(stdiouiFlag.Name) {
|
||||
log.Info("Using stdin/stdout as UI-channel")
|
||||
ui = core.NewStdIOUI()
|
||||
|
|
@ -650,6 +688,7 @@ func signer(c *cli.Context) error {
|
|||
api core.ExternalAPI
|
||||
pwStorage storage.Storage = &storage.NoStorage{}
|
||||
)
|
||||
|
||||
configDir := c.String(configdirFlag.Name)
|
||||
if stretchedKey, err := readMasterKey(c, ui); err != nil {
|
||||
log.Warn("Failed to open master, rules disabled", "err", err)
|
||||
|
|
@ -727,6 +766,7 @@ func signer(c *cli.Context) error {
|
|||
Service: api,
|
||||
},
|
||||
}
|
||||
|
||||
if c.Bool(utils.HTTPEnabledFlag.Name) {
|
||||
vhosts := utils.SplitAndTrim(c.String(utils.HTTPVirtualHostsFlag.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)
|
||||
}()
|
||||
}
|
||||
|
||||
if !c.Bool(utils.IPCDisabledFlag.Name) {
|
||||
givenPath := c.String(utils.IPCPathFlag.Name)
|
||||
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)
|
||||
}()
|
||||
}
|
||||
|
||||
if c.Bool(testFlag.Name) {
|
||||
log.Info("Performing UI test")
|
||||
go testExternalUI(apiImpl)
|
||||
|
|
@ -816,6 +858,7 @@ func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
|
|||
file string
|
||||
configDir = ctx.String(configdirFlag.Name)
|
||||
)
|
||||
|
||||
if ctx.IsSet(signerSecretFlag.Name) {
|
||||
file = ctx.String(signerSecretFlag.Name)
|
||||
} else {
|
||||
|
|
@ -824,6 +867,7 @@ func readMasterKey(ctx *cli.Context, ui core.UIClientAPI) ([]byte, error) {
|
|||
if err := checkFile(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cipherKey, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -1215,5 +1259,6 @@ These data types are defined in the channel between clef and the UI`)
|
|||
for _, elem := range output {
|
||||
fmt.Println(elem)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ func TestMain(m *testing.M) {
|
|||
if reexec.Init() {
|
||||
return
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
|
|
@ -63,9 +64,11 @@ func runClef(t *testing.T, args ...string) *testproc {
|
|||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
os.RemoveAll(ddir)
|
||||
})
|
||||
|
||||
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
|
||||
// function will prevent any tests from running.
|
||||
tt.Run(registeredName, args...)
|
||||
|
||||
return tt
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
|
|||
doneCh = make(chan enode.Iterator, len(c.iters))
|
||||
liveIters = len(c.iters)
|
||||
)
|
||||
|
||||
if nthreads < 1 {
|
||||
nthreads = 1
|
||||
}
|
||||
|
|
@ -86,6 +87,7 @@ func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
|
|||
for _, it := range c.iters {
|
||||
go c.runIterator(doneCh, it)
|
||||
}
|
||||
|
||||
var (
|
||||
added uint64
|
||||
updated uint64
|
||||
|
|
@ -94,10 +96,13 @@ func (c *crawler) run(timeout time.Duration, nthreads int) nodeSet {
|
|||
removed uint64
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
|
||||
wg.Add(nthreads)
|
||||
|
||||
for i := 0; i < nthreads; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
for {
|
||||
select {
|
||||
case n := <-c.ch:
|
||||
|
|
@ -183,6 +188,7 @@ func (c *crawler) updateNode(n *enode.Node) int {
|
|||
// Request the node record.
|
||||
status := nodeUpdated
|
||||
node.LastCheck = truncNow()
|
||||
|
||||
if nn, err := c.disc.RequestENR(n); err != nil {
|
||||
if node.Score == 0 {
|
||||
// Node doesn't implement EIP-868.
|
||||
|
|
@ -206,10 +212,13 @@ func (c *crawler) updateNode(n *enode.Node) int {
|
|||
if node.Score <= 0 {
|
||||
log.Debug("Removing node", "id", n.ID())
|
||||
delete(c.output, n.ID())
|
||||
|
||||
return nodeRemoved
|
||||
}
|
||||
|
||||
log.Debug("Updating node", "id", n.ID(), "seq", n.Seq(), "score", node.Score)
|
||||
c.output[n.ID()] = node
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,18 +282,25 @@ func parseExtAddr(spec string) (ip net.IP, port int, ok bool) {
|
|||
if ip != nil {
|
||||
return ip, 0, true
|
||||
}
|
||||
|
||||
host, portstr, err := net.SplitHostPort(spec)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
ip = net.ParseIP(host)
|
||||
|
||||
if ip == nil {
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
port, err = strconv.Atoi(portstr)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, false
|
||||
}
|
||||
|
||||
return ip, port, true
|
||||
}
|
||||
|
||||
|
|
@ -326,7 +333,9 @@ func listen(ctx *cli.Context, ln *enode.LocalNode) *net.UDPConn {
|
|||
if !ok {
|
||||
exit(fmt.Errorf("-%s: invalid external address %q", extAddrFlag.Name, extAddr))
|
||||
}
|
||||
|
||||
ln.SetStaticIP(ip)
|
||||
|
||||
if port != 0 {
|
||||
ln.SetFallbackUDP(port)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
|
|||
|
||||
// Iterate over the new records and inject anything missing.
|
||||
log.Info("Updating DNS entries")
|
||||
|
||||
created := 0
|
||||
updated := 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)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Updated DNS entries", "new", created, "updated", updated, "untouched", skipped)
|
||||
// Iterate over the old records and delete anything stale.
|
||||
deleted := 0
|
||||
|
||||
log.Info("Deleting stale DNS entries")
|
||||
for path, entry := range existing {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Deleted stale DNS entries", "count", deleted)
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ func makeDeletionChanges(records map[string]recordSet, keep map[string]string) [
|
|||
if _, ok := keep[path]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Debug(fmt.Sprintf("Deleting %s = %s", path, strings.Join(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
|
||||
req.HostedZoneId = &c.zoneID
|
||||
existing := make(map[string]recordSet)
|
||||
|
||||
log.Info("Loading existing TXT records", "name", name, "zone", c.zoneID)
|
||||
for page := 0; ; page++ {
|
||||
log.Debug("Loading existing TXT records", "name", name, "zone", c.zoneID, "page", page)
|
||||
|
|
|
|||
|
|
@ -381,6 +381,7 @@ func writeTreeMetadata(directory string, def *dnsDefinition) {
|
|||
exit(err)
|
||||
}
|
||||
metaFile, _ := treeDefinitionFiles(directory)
|
||||
|
||||
if err := os.WriteFile(metaFile, metaJSON, 0644); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
|
@ -410,6 +411,7 @@ func writeTXTJSON(file string, txt map[string]string) {
|
|||
fmt.Println()
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.WriteFile(file, txtJSON, 0644); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ func loadChain(chainfile string, genesis string) (*Chain, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gblock := gen.ToBlock()
|
||||
|
||||
blocks, err := blocksFromFile(chainfile, gblock)
|
||||
|
|
|
|||
|
|
@ -208,14 +208,18 @@ loop:
|
|||
// node, and one for receiving messages from the node.
|
||||
func (s *Suite) createSendAndRecvConns() (*Conn, *Conn, error) {
|
||||
sendConn, err := s.dial()
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("dial failed: %v", err)
|
||||
}
|
||||
|
||||
recvConn, err := s.dial()
|
||||
|
||||
if err != nil {
|
||||
sendConn.Close()
|
||||
return nil, nil, fmt.Errorf("dial failed: %v", err)
|
||||
}
|
||||
|
||||
return sendConn, recvConn, nil
|
||||
}
|
||||
|
||||
|
|
@ -235,10 +239,12 @@ func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
|
|||
if err != nil {
|
||||
return errorf("could not get headers for inbound header request: %v", err)
|
||||
}
|
||||
|
||||
resp := &BlockHeaders{
|
||||
RequestId: msg.ReqID(),
|
||||
BlockHeadersPacket: eth.BlockHeadersPacket(headers),
|
||||
}
|
||||
|
||||
if err := c.Write(resp); err != nil {
|
||||
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 errorf("no message received within %v", timeout)
|
||||
}
|
||||
|
||||
|
|
@ -263,10 +270,13 @@ func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, reqID uint
|
|||
// wait for response
|
||||
msg := c.waitForResponse(chain, timeout, request.RequestId)
|
||||
resp, ok := msg.(*BlockHeaders)
|
||||
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
|
||||
}
|
||||
|
||||
headers := []*types.Header(resp.BlockHeadersPacket)
|
||||
|
||||
return headers, nil
|
||||
}
|
||||
|
||||
|
|
@ -591,21 +601,26 @@ func (s *Suite) hashAnnounce() error {
|
|||
// Announcement sent, now wait for a header request
|
||||
msg := sendConn.Read()
|
||||
blockHeaderReq, ok := msg.(*GetBlockHeaders)
|
||||
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected %s", pretty.Sdump(msg))
|
||||
}
|
||||
|
||||
if blockHeaderReq.Amount != 1 {
|
||||
return fmt.Errorf("unexpected number of block headers requested: %v", blockHeaderReq.Amount)
|
||||
}
|
||||
|
||||
if blockHeaderReq.Origin.Hash != announcement.Hash {
|
||||
return fmt.Errorf("unexpected block header requested. Announced:\n %v\n Remote request:\n%v",
|
||||
pretty.Sdump(announcement),
|
||||
pretty.Sdump(blockHeaderReq))
|
||||
}
|
||||
|
||||
err = sendConn.Write(&BlockHeaders{
|
||||
RequestId: blockHeaderReq.ReqID(),
|
||||
BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write to connection: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
|
|||
for i := 1; i <= 65; i++ {
|
||||
accPaths = append(accPaths, pathTo(i))
|
||||
}
|
||||
|
||||
empty := types.EmptyCodeHash
|
||||
for i, tc := range []trieNodesTest{
|
||||
{
|
||||
|
|
|
|||
|
|
@ -197,13 +197,16 @@ func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to get expected headers for request 1: %v", err)
|
||||
}
|
||||
|
||||
expected2, err := s.chain.GetHeaders(req2)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get expected headers for request 2: %v", err)
|
||||
}
|
||||
|
||||
if !headersMatch(expected1, headers1.BlockHeadersPacket) {
|
||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
|
||||
}
|
||||
|
||||
if !headersMatch(expected2, headers2.BlockHeadersPacket) {
|
||||
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 {
|
||||
t.Fatalf("failed to write to connection: %v", err)
|
||||
}
|
||||
|
||||
if err = conn.Write(request2); err != nil {
|
||||
t.Fatalf("failed to write to connection: %v", err)
|
||||
}
|
||||
|
|
@ -266,13 +270,16 @@ func (s *Suite) TestSameRequestID(t *utesting.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to get expected block headers: %v", err)
|
||||
}
|
||||
|
||||
expected2, err := s.chain.GetHeaders(request2)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get expected block headers: %v", err)
|
||||
}
|
||||
|
||||
if !headersMatch(expected1, headers1.BlockHeadersPacket) {
|
||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
|
||||
}
|
||||
|
||||
if !headersMatch(expected2, headers2.BlockHeadersPacket) {
|
||||
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
|
||||
}
|
||||
|
|
@ -299,6 +306,7 @@ func (s *Suite) TestZeroRequestID(t *utesting.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to get block headers: %v", err)
|
||||
}
|
||||
|
||||
expected, err := s.chain.GetHeaders(req)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get expected block headers: %v", err)
|
||||
|
|
@ -336,8 +344,10 @@ func (s *Suite) TestGetBlockBodies(t *utesting.T) {
|
|||
if !ok {
|
||||
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
|
||||
}
|
||||
|
||||
bodies := resp.BlockBodiesPacket
|
||||
t.Logf("received %d block bodies", len(bodies))
|
||||
|
||||
if len(bodies) != len(req.GetBlockBodiesPacket) {
|
||||
t.Fatalf("wrong bodies in response: expected %d 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] {
|
||||
t.Logf("Testing malicious announcement: %v\n", i)
|
||||
|
||||
conn, err := s.dial()
|
||||
if err != nil {
|
||||
t.Fatalf("dial failed: %v", err)
|
||||
|
|
@ -480,10 +491,12 @@ func (s *Suite) TestLargeTxRequest(t *utesting.T) {
|
|||
for _, hash := range hashMap {
|
||||
hashes = append(hashes, hash)
|
||||
}
|
||||
|
||||
getTxReq := &GetPooledTransactions{
|
||||
RequestId: 1234,
|
||||
GetPooledTransactionsPacket: hashes,
|
||||
}
|
||||
|
||||
if err = conn.Write(getTxReq); err != nil {
|
||||
t.Fatalf("could not write to conn: %v", err)
|
||||
}
|
||||
|
|
@ -514,9 +527,11 @@ func (s *Suite) TestNewPooledTxs(t *utesting.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to generate transactions: %v", err)
|
||||
}
|
||||
|
||||
hashes := make([]common.Hash, len(txs))
|
||||
types := make([]byte, len(txs))
|
||||
sizes := make([]uint32, len(txs))
|
||||
|
||||
for i, tx := range txs {
|
||||
hashes[i] = tx.Hash()
|
||||
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}
|
||||
|
||||
if conn.negotiatedProtoVersion < eth.ETH68 {
|
||||
ann = NewPooledTransactionHashes66(hashes)
|
||||
}
|
||||
|
||||
err = conn.Write(ann)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to write to connection: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,8 +45,11 @@ func TestEthSuite(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("could not create new test suite: %v", err)
|
||||
}
|
||||
|
||||
for _, test := range suite.EthTests() {
|
||||
test := test
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
|
||||
if result[0].Failed {
|
||||
t.Fatal()
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
|
|||
if 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) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
for index, gotHash := range txHashes {
|
||||
if gotHash == tx.Hash() {
|
||||
if msg.Sizes[index] != uint32(tx.Size()) {
|
||||
return fmt.Errorf("invalid tx size: got %v want %v", msg.Sizes[index], tx.Size())
|
||||
}
|
||||
|
||||
if 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 fmt.Errorf("missing transaction announcement: got %v missing %v", txHashes, tx.Hash())
|
||||
|
||||
default:
|
||||
|
|
@ -165,6 +169,7 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T) error {
|
|||
|
||||
for i, tx := range badTxs {
|
||||
t.Logf("Testing malicious tx propagation: %v\n", i)
|
||||
|
||||
if err = sendMaliciousTx(s, tx); err != nil {
|
||||
return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,24 +183,28 @@ func (c *Conn) Read() Message {
|
|||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return (*GetBlockHeaders)(ethMsg)
|
||||
case (BlockHeaders{}).Code():
|
||||
ethMsg := new(eth.BlockHeadersPacket66)
|
||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return (*BlockHeaders)(ethMsg)
|
||||
case (GetBlockBodies{}).Code():
|
||||
ethMsg := new(eth.GetBlockBodiesPacket66)
|
||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return (*GetBlockBodies)(ethMsg)
|
||||
case (BlockBodies{}).Code():
|
||||
ethMsg := new(eth.BlockBodiesPacket66)
|
||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return (*BlockBodies)(ethMsg)
|
||||
case (NewBlock{}).Code():
|
||||
msg = new(NewBlock)
|
||||
|
|
@ -214,18 +218,21 @@ func (c *Conn) Read() Message {
|
|||
if err := rlp.DecodeBytes(rawData, ethMsg); err == nil {
|
||||
return ethMsg
|
||||
}
|
||||
|
||||
msg = new(NewPooledTransactionHashes66)
|
||||
case (GetPooledTransactions{}.Code()):
|
||||
ethMsg := new(eth.GetPooledTransactionsPacket66)
|
||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return (*GetPooledTransactions)(ethMsg)
|
||||
case (PooledTransactions{}.Code()):
|
||||
ethMsg := new(eth.PooledTransactionsPacket66)
|
||||
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return (*PooledTransactions)(ethMsg)
|
||||
default:
|
||||
msg = errorf("invalid message code: %d", code)
|
||||
|
|
@ -235,8 +242,10 @@ func (c *Conn) Read() Message {
|
|||
if err := rlp.DecodeBytes(rawData, msg); err != nil {
|
||||
return errorf("could not rlp decode message: %v", err)
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
||||
|
||||
return errorf("invalid message: %s", string(rawData))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,9 @@ func keyToID(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(n.ID())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +113,9 @@ func keyToURL(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(n.URLv4())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +124,9 @@ func keyToRecord(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(n.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -141,16 +147,20 @@ func makeRecord(ctx *cli.Context) (*enode.Node, error) {
|
|||
}
|
||||
|
||||
var r enr.Record
|
||||
|
||||
if host != "" {
|
||||
ip := net.ParseIP(host)
|
||||
if ip == nil {
|
||||
return nil, fmt.Errorf("invalid IP address %q", host)
|
||||
}
|
||||
|
||||
r.Set(enr.IP(ip))
|
||||
}
|
||||
|
||||
if udp != 0 {
|
||||
r.Set(enr.UDP(udp))
|
||||
}
|
||||
|
||||
if tcp != 0 {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return enode.New(enode.ValidSchemes, &r)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,14 +63,17 @@ func main() {
|
|||
func commandHasFlag(ctx *cli.Context, flag cli.Flag) bool {
|
||||
names := flag.Names()
|
||||
set := make(map[string]struct{}, len(names))
|
||||
|
||||
for _, name := range names {
|
||||
set[name] = struct{}{}
|
||||
}
|
||||
|
||||
for _, fn := range ctx.FlagNames() {
|
||||
if _, ok := set[fn]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +82,7 @@ func getNodeArg(ctx *cli.Context) *enode.Node {
|
|||
if ctx.NArg() < 1 {
|
||||
exit("missing node as command-line argument")
|
||||
}
|
||||
|
||||
n, err := parseNode(ctx.Args().First())
|
||||
if err != nil {
|
||||
exit(err)
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ func writeNodesJSON(file string, nodes nodeSet) {
|
|||
os.Stdout.Write(nodesJSON)
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.WriteFile(file, nodesJSON, 0644); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,10 +105,12 @@ func rlpxEthTest(ctx *cli.Context) error {
|
|||
if ctx.NArg() < 3 {
|
||||
exit("missing path to chain.rlp as command-line argument")
|
||||
}
|
||||
|
||||
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
|
||||
if err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
||||
return runTests(ctx, suite.EthTests())
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +119,7 @@ func rlpxSnapTest(ctx *cli.Context) error {
|
|||
if ctx.NArg() < 3 {
|
||||
exit("missing path to chain.rlp as command-line argument")
|
||||
}
|
||||
|
||||
suite, err := ethtest.NewSuite(getNodeArg(ctx), ctx.Args().Get(1), ctx.Args().Get(2))
|
||||
if err != nil {
|
||||
exit(err)
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ func getMessage(ctx *cli.Context, msgarg int) []byte {
|
|||
if ctx.NArg() > msgarg {
|
||||
utils.Fatalf("Can't use --msgfile and message argument at the same time.")
|
||||
}
|
||||
|
||||
msg, err := os.ReadFile(file)
|
||||
if err != nil {
|
||||
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 {
|
||||
return []byte(ctx.Args().Get(msgarg))
|
||||
}
|
||||
|
||||
utils.Fatalf("Invalid number of arguments: want %d, got %d", msgarg+1, ctx.NArg())
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,14 +48,18 @@ func blockTestCmd(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var tests map[string]tests.BlockTest
|
||||
|
||||
if err = json.Unmarshal(src, &tests); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
if err := test.Run(false); err != nil {
|
||||
return fmt.Errorf("test %v: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ func (i *bbInput) ToBlock() *types.Block {
|
|||
if header.Difficulty != nil {
|
||||
header.Difficulty = i.Header.Difficulty
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if withdrawalsStr != stdinSelector && withdrawalsStr != "" {
|
||||
var withdrawals []*types.Withdrawal
|
||||
if err := readFile(withdrawalsStr, "withdrawals", &withdrawals); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inputData.Withdrawals = withdrawals
|
||||
}
|
||||
if txsStr != stdinSelector {
|
||||
|
|
@ -367,6 +370,7 @@ func dispatchBlock(ctx *cli.Context, baseDir string, block *types.Block) error {
|
|||
Rlp hexutil.Bytes `json:"rlp"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
}
|
||||
|
||||
enc := blockInfo{
|
||||
Rlp: raw,
|
||||
Hash: block.Hash(),
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
return nil, nil, err
|
||||
}
|
||||
vmConfig.Tracer = tracer
|
||||
|
||||
statedb.SetTxContext(tx.Hash(), txIndex)
|
||||
|
||||
var (
|
||||
|
|
@ -190,6 +191,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
statedb.RevertToSnapshot(snapshot)
|
||||
log.Info("rejected tx", "index", i, "hash", tx.Hash(), "from", msg.From, "error", err)
|
||||
rejectedTxs = append(rejectedTxs, &rejectedTx{i, err.Error()})
|
||||
|
||||
gaspool.SetGas(prevGas)
|
||||
continue
|
||||
}
|
||||
|
|
@ -285,6 +287,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||
GasUsed: (math.HexOrDecimal64)(gasUsed),
|
||||
BaseFee: (*math.HexOrDecimal256)(vmContext.BaseFee),
|
||||
}
|
||||
|
||||
if pre.Env.Withdrawals != nil {
|
||||
h := types.DeriveSha(types.Withdrawals(pre.Env.Withdrawals), trie.NewStackTrie(nil))
|
||||
execRs.WithdrawalsRoot = &h
|
||||
|
|
|
|||
|
|
@ -265,8 +265,10 @@ func Transition(ctx *cli.Context) error {
|
|||
if chainConfig.IsShanghai(prestate.Env.Number) && prestate.Env.Withdrawals == nil {
|
||||
return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section"))
|
||||
}
|
||||
|
||||
isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0
|
||||
env := prestate.Env
|
||||
|
||||
if isMerged {
|
||||
// post-merge:
|
||||
// - random must be supplied
|
||||
|
|
@ -277,6 +279,7 @@ func Transition(ctx *cli.Context) error {
|
|||
case env.Difficulty != nil && env.Difficulty.BitLen() != 0:
|
||||
return NewError(ErrorConfig, errors.New("post-merge difficulty must be zero (or omitted) in env"))
|
||||
}
|
||||
|
||||
prestate.Env.Difficulty = nil
|
||||
} else if env.Difficulty == nil {
|
||||
// pre-merge:
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
genesisConfig *core.Genesis
|
||||
preimages = ctx.Bool(DumpFlag.Name)
|
||||
)
|
||||
|
||||
if ctx.Bool(MachineFlag.Name) {
|
||||
tracer = logger.NewJSONLogger(logconfig, os.Stdout)
|
||||
} else if ctx.Bool(DebugFlag.Name) {
|
||||
|
|
@ -136,6 +137,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
} else {
|
||||
debugLogger = logger.NewStructLogger(logconfig)
|
||||
}
|
||||
|
||||
if ctx.String(GenesisFlag.Name) != "" {
|
||||
gen := readGenesis(ctx.String(GenesisFlag.Name))
|
||||
genesisConfig = gen
|
||||
|
|
@ -149,6 +151,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
statedb, _ = state.New(common.Hash{}, sdb, nil)
|
||||
genesisConfig = new(core.Genesis)
|
||||
}
|
||||
|
||||
if ctx.String(SenderFlag.Name) != "" {
|
||||
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
||||
}
|
||||
|
|
@ -159,6 +162,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
var code []byte
|
||||
|
||||
codeFileFlag := ctx.String(CodeFileFlag.Name)
|
||||
codeFlag := ctx.String(CodeFlag.Name)
|
||||
|
||||
|
|
@ -202,6 +206,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
}
|
||||
code = common.Hex2Bytes(bin)
|
||||
}
|
||||
|
||||
initialGas := ctx.Uint64(GasFlag.Name)
|
||||
if genesisConfig.GasLimit != 0 {
|
||||
initialGas = genesisConfig.GasLimit
|
||||
|
|
@ -241,6 +246,7 @@ func runCmd(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
var hexInput []byte
|
||||
|
||||
if inputFileFlag := ctx.String(InputFileFlag.Name); inputFileFlag != "" {
|
||||
var err error
|
||||
if hexInput, err = os.ReadFile(inputFileFlag); err != nil {
|
||||
|
|
@ -250,14 +256,18 @@ func runCmd(ctx *cli.Context) error {
|
|||
} else {
|
||||
hexInput = []byte(ctx.String(InputFlag.Name))
|
||||
}
|
||||
|
||||
hexInput = bytes.TrimSpace(hexInput)
|
||||
|
||||
if len(hexInput)%2 != 0 {
|
||||
fmt.Println("input length must be even")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
input := common.FromHex(string(hexInput))
|
||||
|
||||
var execFunc func() ([]byte, uint64, error)
|
||||
|
||||
if ctx.Bool(CreateFlag.Name) {
|
||||
input = append(code, input...)
|
||||
execFunc = func() ([]byte, uint64, error) {
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
if s != nil {
|
||||
root := s.IntermediateRoot(false)
|
||||
result.Root = &root
|
||||
|
||||
if ctx.Bool(MachineFlag.Name) {
|
||||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||
}
|
||||
|
|
@ -110,6 +111,7 @@ func stateTestCmd(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
// Test failed, mark as so and dump any state to aid debugging
|
||||
result.Pass, result.Error = false, err.Error()
|
||||
|
||||
if ctx.Bool(DumpFlag.Name) && s != nil {
|
||||
dump := s.RawDump(nil)
|
||||
result.State = &dump
|
||||
|
|
|
|||
|
|
@ -420,6 +420,7 @@ func (args *b11rInput) get(base string) []string {
|
|||
out = append(out, "--input.ommers")
|
||||
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||
}
|
||||
|
||||
if opt := args.inWithdrawals; opt != "" {
|
||||
out = append(out, "--input.withdrawals")
|
||||
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ func main() {
|
|||
pass := strings.TrimSuffix(string(blob), "\n")
|
||||
|
||||
ks := keystore.NewKeyStore(filepath.Join(os.Getenv("HOME"), ".faucet", "keys"), keystore.StandardScryptN, keystore.StandardScryptP)
|
||||
|
||||
if blob, err = os.ReadFile(*accJSONFlag); err != nil {
|
||||
log.Crit("Failed to read account key contents", "file", *accJSONFlag, "err", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ func ambiguousAddrRecovery(ks *keystore.KeyStore, err *keystore.AmbiguousAddrErr
|
|||
}
|
||||
fmt.Println("Testing your password against all of them...")
|
||||
var match *accounts.Account
|
||||
|
||||
for i, a := range err.Matches {
|
||||
if e := ks.Unlock(a, auth); e == nil {
|
||||
match = &err.Matches[i]
|
||||
|
|
@ -302,9 +303,11 @@ func accountUpdate(ctx *cli.Context) error {
|
|||
}
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
backends := stack.AccountManager().Backends(keystore.KeyStoreType)
|
||||
|
||||
if len(backends) == 0 {
|
||||
utils.Fatalf("Keystore is not available")
|
||||
}
|
||||
|
||||
ks := backends[0].(*keystore.KeyStore)
|
||||
|
||||
for _, addr := range ctx.Args().Slice() {
|
||||
|
|
@ -321,6 +324,7 @@ func importWallet(ctx *cli.Context) error {
|
|||
if ctx.Args().Len() != 1 {
|
||||
utils.Fatalf("keyfile must be given as the only argument")
|
||||
}
|
||||
|
||||
keyfile := ctx.Args().First()
|
||||
keyJSON, err := os.ReadFile(keyfile)
|
||||
if err != nil {
|
||||
|
|
@ -334,6 +338,7 @@ func importWallet(ctx *cli.Context) error {
|
|||
if len(backends) == 0 {
|
||||
utils.Fatalf("Keystore is not available")
|
||||
}
|
||||
|
||||
ks := backends[0].(*keystore.KeyStore)
|
||||
acct, err := ks.ImportPreSaleKey(keyJSON, passphrase)
|
||||
if err != nil {
|
||||
|
|
@ -347,6 +352,7 @@ func accountImport(ctx *cli.Context) error {
|
|||
if ctx.Args().Len() != 1 {
|
||||
utils.Fatalf("keyfile must be given as the only argument")
|
||||
}
|
||||
|
||||
keyfile := ctx.Args().First()
|
||||
key, err := crypto.LoadECDSA(keyfile)
|
||||
if err != nil {
|
||||
|
|
@ -359,6 +365,7 @@ func accountImport(ctx *cli.Context) error {
|
|||
if len(backends) == 0 {
|
||||
utils.Fatalf("Keystore is not available")
|
||||
}
|
||||
|
||||
ks := backends[0].(*keystore.KeyStore)
|
||||
acct, err := ks.ImportECDSA(key, passphrase)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ func TestAccountListEmpty(t *testing.T) {
|
|||
|
||||
func TestAccountList(t *testing.T) {
|
||||
datadir := tmpDatadirWithKeystore(t)
|
||||
|
||||
var want = `
|
||||
Account #0: {7ef5a6135f1fd6a02593eedc869c6d41d934aef8} keystore://{{.Datadir}}/keystore/UTC--2016-03-22T12-57-55.920751759Z--7ef5a6135f1fd6a02593eedc869c6d41d934aef8
|
||||
Account #1: {f466859ead1932d743d622cb74fc058882e8648a} keystore://{{.Datadir}}/keystore/aaa
|
||||
|
|
@ -122,12 +123,14 @@ func TestAccountHelp(t *testing.T) {
|
|||
|
||||
geth := runGeth(t, "account", "-h")
|
||||
geth.WaitExit()
|
||||
|
||||
if have, want := geth.ExitStatus(), 0; have != want {
|
||||
t.Errorf("exit error, have %d want %d", have, want)
|
||||
}
|
||||
|
||||
geth = runGeth(t, "account", "import", "-h")
|
||||
geth.WaitExit()
|
||||
|
||||
if have, want := geth.ExitStatus(), 0; 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) {
|
||||
dir := t.TempDir()
|
||||
keyfile := filepath.Join(dir, "key.prv")
|
||||
|
||||
if err := os.WriteFile(keyfile, []byte(key), 0600); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
passwordFile := filepath.Join(dir, "password.txt")
|
||||
|
||||
if err := os.WriteFile(passwordFile, []byte("foobar"), 0600); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
geth := runGeth(t, "--lightkdf", "account", "import", "-password", passwordFile, keyfile)
|
||||
defer geth.ExpectExit()
|
||||
geth.Expect(expected)
|
||||
|
|
|
|||
|
|
@ -36,26 +36,31 @@ func (t *testHandler) ServeHTTP(out http.ResponseWriter, in *http.Request) {
|
|||
// that custom headers are forwarded to the target.
|
||||
func TestAttachWithHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ln, err := net.Listen("tcp", "localhost:0")
|
||||
|
||||
if err != nil {
|
||||
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:
|
||||
//
|
||||
// testReceiveHeaders(t, ln, "-H", "first: one", "-H", "second: two", "attach", fmt.Sprintf("http://localhost:%d", port))
|
||||
// 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
|
||||
// that custom headers are forwarded to the target.
|
||||
func TestRemoteDbWithHeaders(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ln, err := net.Listen("tcp", "localhost:0")
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
port := ln.Addr().(*net.TCPAddr).Port
|
||||
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()
|
||||
|
||||
var ok uint32
|
||||
|
||||
server := &http.Server{
|
||||
Addr: "localhost:0",
|
||||
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)
|
||||
}}}
|
||||
go server.Serve(ln)
|
||||
|
||||
defer server.Close()
|
||||
runGeth(t, gethArgs...).WaitExit()
|
||||
|
||||
if atomic.LoadUint32(&ok) != 1 {
|
||||
t.Fatal("Test fail, expected invocation to succeed")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ func initGenesis(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
utils.Fatalf("Failed to open database: %v", err)
|
||||
}
|
||||
|
||||
triedb := trie.NewDatabaseWithConfig(chaindb, &trie.Config{
|
||||
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 {
|
||||
utils.Fatalf("could not encode genesis: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
// dump whatever already exists in the datadir
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||
db, err := stack.OpenDatabase(name, 0, 0, "", true)
|
||||
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
genesis, err := core.ReadGenesis(db)
|
||||
|
||||
if err != nil {
|
||||
utils.Fatalf("failed to read genesis: %s", err)
|
||||
}
|
||||
|
||||
db.Close()
|
||||
|
||||
if err := json.NewEncoder(os.Stdout).Encode(*genesis); err != nil {
|
||||
utils.Fatalf("could not encode stored genesis: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.DataDirFlag.Name) {
|
||||
utils.Fatalf("no existing datadir at %s", stack.Config().DataDir)
|
||||
}
|
||||
|
||||
utils.Fatalf("no network preset provided. no exisiting genesis in the default datadir")
|
||||
return nil
|
||||
}
|
||||
|
|
@ -337,6 +347,7 @@ func exportChain(ctx *cli.Context) error {
|
|||
|
||||
var err error
|
||||
fp := ctx.Args().First()
|
||||
|
||||
if ctx.Args().Len() < 3 {
|
||||
err = utils.ExportChain(chain, fp)
|
||||
} else {
|
||||
|
|
@ -465,6 +476,7 @@ func dump(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
config := &trie.Config{
|
||||
Preimages: true, // always enable preimage lookup
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
|
|||
}
|
||||
|
||||
utils.SetEthConfig(ctx, stack, &cfg.Eth)
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
|
||||
if ctx.IsSet(utils.MetricsEnabledFlag.Name) {
|
||||
cfg.Metrics.Enabled = ctx.Bool(utils.MetricsEnabledFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsEnabledExpensiveFlag.Name) {
|
||||
cfg.Metrics.EnabledExpensive = ctx.Bool(utils.MetricsEnabledExpensiveFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsHTTPFlag.Name) {
|
||||
cfg.Metrics.HTTP = ctx.String(utils.MetricsHTTPFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsPortFlag.Name) {
|
||||
cfg.Metrics.Port = ctx.Int(utils.MetricsPortFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsEnableInfluxDBFlag.Name) {
|
||||
cfg.Metrics.EnableInfluxDB = ctx.Bool(utils.MetricsEnableInfluxDBFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBEndpointFlag.Name) {
|
||||
cfg.Metrics.InfluxDBEndpoint = ctx.String(utils.MetricsInfluxDBEndpointFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBDatabaseFlag.Name) {
|
||||
cfg.Metrics.InfluxDBDatabase = ctx.String(utils.MetricsInfluxDBDatabaseFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBUsernameFlag.Name) {
|
||||
cfg.Metrics.InfluxDBUsername = ctx.String(utils.MetricsInfluxDBUsernameFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBPasswordFlag.Name) {
|
||||
cfg.Metrics.InfluxDBPassword = ctx.String(utils.MetricsInfluxDBPasswordFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
||||
cfg.Metrics.InfluxDBTags = ctx.String(utils.MetricsInfluxDBTagsFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
|
||||
cfg.Metrics.EnableInfluxDBV2 = ctx.Bool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBTokenFlag.Name) {
|
||||
cfg.Metrics.InfluxDBToken = ctx.String(utils.MetricsInfluxDBTokenFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBBucketFlag.Name) {
|
||||
cfg.Metrics.InfluxDBBucket = ctx.String(utils.MetricsInfluxDBBucketFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(utils.MetricsInfluxDBOrganizationFlag.Name) {
|
||||
cfg.Metrics.InfluxDBOrganization = ctx.String(utils.MetricsInfluxDBOrganizationFlag.Name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ func remoteConsole(ctx *cli.Context) error {
|
|||
}
|
||||
endpoint = fmt.Sprintf("%s/bor.ipc", path)
|
||||
}
|
||||
|
||||
client, err := utils.DialRPCWithHeaders(endpoint, ctx.StringSlice(utils.HttpHeaderFlag.Name))
|
||||
if err != nil {
|
||||
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() {
|
||||
b.Write([]byte(fmt.Sprintf("loadScript('%s');", file)))
|
||||
}
|
||||
|
||||
utils.Fatalf(`The "js" command is deprecated. Please use the following instead:
|
||||
geth --exec "%s" console`, b.String())
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -291,9 +291,11 @@ func checkStateContent(ctx *cli.Context) error {
|
|||
prefix []byte
|
||||
start []byte
|
||||
)
|
||||
|
||||
if ctx.NArg() > 1 {
|
||||
return fmt.Errorf("max 1 argument: %v", ctx.Command.ArgsUsage)
|
||||
}
|
||||
|
||||
if ctx.NArg() > 0 {
|
||||
if d, err := hexutil.Decode(ctx.Args().First()); err != nil {
|
||||
return fmt.Errorf("failed to hex-decode 'start': %v", err)
|
||||
|
|
@ -301,11 +303,13 @@ func checkStateContent(ctx *cli.Context) error {
|
|||
start = d
|
||||
}
|
||||
}
|
||||
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||
defer db.Close()
|
||||
|
||||
var (
|
||||
it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32)
|
||||
hasher = crypto.NewKeccakState()
|
||||
|
|
@ -315,28 +319,37 @@ func checkStateContent(ctx *cli.Context) error {
|
|||
startTime = time.Now()
|
||||
lastLog = time.Now()
|
||||
)
|
||||
|
||||
for it.Next() {
|
||||
count++
|
||||
|
||||
k := it.Key()
|
||||
v := it.Value()
|
||||
|
||||
hasher.Reset()
|
||||
hasher.Write(v)
|
||||
hasher.Read(got)
|
||||
|
||||
if !bytes.Equal(k, got) {
|
||||
errs++
|
||||
|
||||
fmt.Printf("Error at %#x\n", k)
|
||||
fmt.Printf(" Hash: %#x\n", got)
|
||||
fmt.Printf(" Data: %#x\n", v)
|
||||
}
|
||||
|
||||
if time.Since(lastLog) > 8*time.Second {
|
||||
log.Info("Iterating the database", "at", fmt.Sprintf("%#x", k), "elapsed", common.PrettyDuration(time.Since(startTime)))
|
||||
lastLog = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
if err := it.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Iterated the state content", "errors", errs, "items", count)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -454,6 +467,7 @@ func dbPut(ctx *cli.Context) error {
|
|||
data []byte
|
||||
err error
|
||||
)
|
||||
|
||||
key, err = common.ParseHexOrString(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
log.Info("Could not decode the key", "error", err)
|
||||
|
|
@ -490,30 +504,36 @@ func dbDumpTrie(ctx *cli.Context) error {
|
|||
max = int64(-1)
|
||||
err error
|
||||
)
|
||||
|
||||
if state, err = hexutil.Decode(ctx.Args().Get(0)); err != nil {
|
||||
log.Info("Could not decode the state root", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if account, err = hexutil.Decode(ctx.Args().Get(1)); err != nil {
|
||||
log.Info("Could not decode the account hash", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if storage, err = hexutil.Decode(ctx.Args().Get(2)); err != nil {
|
||||
log.Info("Could not decode the storage trie root", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if ctx.NArg() > 3 {
|
||||
if start, err = hexutil.Decode(ctx.Args().Get(3)); err != nil {
|
||||
log.Info("Could not decode the seek position", "error", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.NArg() > 4 {
|
||||
if max, err = strconv.ParseInt(ctx.Args().Get(4), 10, 64); err != nil {
|
||||
log.Info("Could not decode the max count", "error", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
id := trie.StorageTrieID(common.BytesToHash(state), common.BytesToHash(account), common.BytesToHash(storage))
|
||||
theTrie, err := trie.New(id, trie.NewDatabase(db))
|
||||
if err != nil {
|
||||
|
|
@ -536,16 +556,21 @@ func freezerInspect(ctx *cli.Context) error {
|
|||
if ctx.NArg() < 4 {
|
||||
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
|
||||
}
|
||||
|
||||
var (
|
||||
freezer = ctx.Args().Get(0)
|
||||
table = ctx.Args().Get(1)
|
||||
)
|
||||
|
||||
start, err := strconv.ParseInt(ctx.Args().Get(2), 10, 64)
|
||||
|
||||
if err != nil {
|
||||
log.Info("Could not read start-param", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
end, err := strconv.ParseInt(ctx.Args().Get(3), 10, 64)
|
||||
|
||||
if err != nil {
|
||||
log.Info("Could not read count param", "err", err)
|
||||
return err
|
||||
|
|
@ -553,6 +578,7 @@ func freezerInspect(ctx *cli.Context) error {
|
|||
stack, _ := makeConfigNode(ctx)
|
||||
ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name))
|
||||
stack.Close()
|
||||
|
||||
return rawdb.InspectFreezerTable(ancient, freezer, table, start, end)
|
||||
}
|
||||
|
||||
|
|
@ -694,6 +720,7 @@ func showMetaData(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error accessing ancients: %v", err)
|
||||
}
|
||||
|
||||
data := rawdb.ReadChainMetadata(db)
|
||||
data = append(data, []string{"frozen", fmt.Sprintf("%d items", ancients)})
|
||||
data = append(data, []string{"snapshotGenerator", snapshot.ParseGeneratorStatus(rawdb.ReadSnapshotGenerator(db))})
|
||||
|
|
|
|||
|
|
@ -33,13 +33,17 @@ func TestExport(t *testing.T) {
|
|||
defer os.Remove(outfile)
|
||||
geth := runGeth(t, "--datadir", initGeth(t), "export", outfile)
|
||||
geth.WaitExit()
|
||||
|
||||
if have, want := geth.ExitStatus(), 0; have != want {
|
||||
t.Errorf("exit error, have %d want %d", have, want)
|
||||
}
|
||||
|
||||
have, err := os.ReadFile(outfile)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := common.FromHex("0xf9026bf90266a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a08758259b018f7bce3d2be2ddb62f325eaeea0a0c188cf96623eab468a4413e03a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000180837a12008080b875000000000000000000000000000000000000000000000000000000000000000002f0d131f1f97aef08aec6e3291b957d9efe71050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0")
|
||||
if !bytes.Equal(have, want) {
|
||||
t.Fatalf("wrong content exported")
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ func TestCustomBackend(t *testing.T) {
|
|||
if strconv.IntSize != 64 {
|
||||
t.Skip("Custom backends are only available on 64-bit platform")
|
||||
}
|
||||
|
||||
genesis := `{
|
||||
"alloc" : {},
|
||||
"coinbase" : "0x0000000000000000000000000000000000000000",
|
||||
|
|
@ -113,13 +114,16 @@ func TestCustomBackend(t *testing.T) {
|
|||
"timestamp" : "0x00",
|
||||
"config" : {}
|
||||
}`
|
||||
|
||||
type backendTest struct {
|
||||
initArgs []string
|
||||
initExpect string
|
||||
execArgs []string
|
||||
execExpect string
|
||||
}
|
||||
|
||||
testfunc := func(t *testing.T, tt backendTest) error {
|
||||
t.Helper()
|
||||
// Create a temporary data directory to use and inspect later
|
||||
datadir := t.TempDir()
|
||||
|
||||
|
|
@ -143,8 +147,10 @@ func TestCustomBackend(t *testing.T) {
|
|||
geth.ExpectRegexp(tt.execExpect)
|
||||
geth.ExpectExit()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
for i, tt := range []backendTest{
|
||||
{ // When not specified, it should default to leveldb
|
||||
execArgs: []string{"--db.engine", "leveldb"},
|
||||
|
|
|
|||
|
|
@ -473,6 +473,7 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon
|
|||
// unlockAccounts unlocks any account specifically requested.
|
||||
func unlockAccounts(ctx *cli.Context, stack *node.Node) {
|
||||
var unlocks []string
|
||||
|
||||
inputs := strings.Split(ctx.String(utils.UnlockedAccountFlag.Name), ",")
|
||||
for _, input := range inputs {
|
||||
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() {
|
||||
utils.Fatalf("Account unlock with HTTP access is forbidden!")
|
||||
}
|
||||
|
||||
backends := stack.AccountManager().Backends(keystore.KeyStoreType)
|
||||
|
||||
if len(backends) == 0 {
|
||||
log.Warn("Failed to unlock accounts, keystore is not available")
|
||||
return
|
||||
}
|
||||
|
||||
ks := backends[0].(*keystore.KeyStore)
|
||||
passwords := utils.MakePasswordList(ctx)
|
||||
for i, account := range unlocks {
|
||||
|
|
|
|||
|
|
@ -131,9 +131,11 @@ func printVersion(ctx *cli.Context) error {
|
|||
|
||||
fmt.Println(strings.Title(clientIdentifier))
|
||||
fmt.Println("Version:", params.VersionWithMeta)
|
||||
|
||||
if git.Commit != "" {
|
||||
fmt.Println("Git Commit:", git.Commit)
|
||||
}
|
||||
|
||||
if git.Date != "" {
|
||||
fmt.Println("Git Commit Date:", git.Date)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ func verifyState(ctx *cli.Context) error {
|
|||
log.Error("Failed to load head block")
|
||||
return errors.New("no head block")
|
||||
}
|
||||
|
||||
snapconfig := snapshot.Config{
|
||||
CacheSize: 256,
|
||||
Recovery: false,
|
||||
|
|
@ -235,6 +236,7 @@ func verifyState(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
log.Info("Verified the state", "root", root)
|
||||
|
||||
return snapshot.CheckDanglingStorage(chaindb)
|
||||
}
|
||||
|
||||
|
|
@ -300,6 +302,7 @@ func traverseState(ctx *cli.Context) error {
|
|||
log.Error("Invalid account encountered during traversal", "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root)
|
||||
storageTrie, err := trie.NewStateTrie(id, triedb)
|
||||
|
|
@ -316,6 +319,7 @@ func traverseState(ctx *cli.Context) error {
|
|||
return storageIter.Err
|
||||
}
|
||||
}
|
||||
|
||||
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||
if !rawdb.HasCode(chaindb, 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)
|
||||
return errors.New("missing account")
|
||||
}
|
||||
|
||||
hasher.Reset()
|
||||
hasher.Write(blob)
|
||||
hasher.Read(got)
|
||||
|
||||
if !bytes.Equal(got, node.Bytes()) {
|
||||
log.Error("Invalid trie node(account)", "hash", node.Hex(), "value", blob)
|
||||
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)
|
||||
return errors.New("invalid account")
|
||||
}
|
||||
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root)
|
||||
storageTrie, err := trie.NewStateTrie(id, triedb)
|
||||
|
|
@ -435,9 +442,11 @@ func traverseRawState(ctx *cli.Context) error {
|
|||
log.Error("Missing trie node(storage)", "hash", node)
|
||||
return errors.New("missing storage")
|
||||
}
|
||||
|
||||
hasher.Reset()
|
||||
hasher.Write(blob)
|
||||
hasher.Read(got)
|
||||
|
||||
if !bytes.Equal(got, node.Bytes()) {
|
||||
log.Error("Invalid trie node(storage)", "hash", node.Hex(), "value", blob)
|
||||
return errors.New("invalid storage node")
|
||||
|
|
@ -453,6 +462,7 @@ func traverseRawState(ctx *cli.Context) error {
|
|||
return storageIter.Error()
|
||||
}
|
||||
}
|
||||
|
||||
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {
|
||||
log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey()))
|
||||
|
|
@ -490,6 +500,7 @@ func dumpState(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
snapConfig := snapshot.Config{
|
||||
CacheSize: 256,
|
||||
Recovery: false,
|
||||
|
|
@ -528,6 +539,7 @@ func dumpState(ctx *cli.Context) error {
|
|||
CodeHash: account.CodeHash,
|
||||
SecureKey: accIt.Hash().Bytes(),
|
||||
}
|
||||
|
||||
if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||
da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash))
|
||||
}
|
||||
|
|
@ -564,10 +576,12 @@ func checkAccount(ctx *cli.Context) error {
|
|||
if ctx.NArg() != 1 {
|
||||
return errors.New("need <address|hash> arg")
|
||||
}
|
||||
|
||||
var (
|
||||
hash common.Hash
|
||||
addr common.Address
|
||||
)
|
||||
|
||||
switch arg := ctx.Args().First(); len(arg) {
|
||||
case 40, 42:
|
||||
addr = common.HexToAddress(arg)
|
||||
|
|
@ -577,15 +591,22 @@ func checkAccount(ctx *cli.Context) error {
|
|||
default:
|
||||
return errors.New("malformed address or hash")
|
||||
}
|
||||
|
||||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||
defer chaindb.Close()
|
||||
|
||||
start := time.Now()
|
||||
|
||||
log.Info("Checking difflayer journal", "address", addr, "hash", hash)
|
||||
|
||||
if err := snapshot.CheckJournalAccount(chaindb, hash); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Checked the snapshot journalled storage", "time", common.PrettyDuration(time.Since(start)))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,9 +77,11 @@ func checkChildren(root verkle.VerkleNode, resolver verkle.NodeResolverFn) error
|
|||
childC := child.ComputeCommitment().Bytes()
|
||||
|
||||
childS, err := resolver(childC[:])
|
||||
|
||||
if bytes.Equal(childC[:], zero[:]) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
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 {
|
||||
return fmt.Errorf("decode error child %x in db: %w", child.ComputeCommitment().Bytes(), err)
|
||||
}
|
||||
|
||||
if err := checkChildren(childN, resolver); err != nil {
|
||||
return fmt.Errorf("%x%w", i, err) // write the path to the erroring node
|
||||
}
|
||||
}
|
||||
case *verkle.LeafNode:
|
||||
// sanity check: ensure at least one value is non-zero
|
||||
|
||||
for i := 0; i < verkle.NodeWidth; i++ {
|
||||
if len(node.Value(i)) != 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Both balance and nonce are 0")
|
||||
case verkle.Empty:
|
||||
// nothing to do
|
||||
|
|
@ -116,24 +119,29 @@ func verifyVerkle(ctx *cli.Context) error {
|
|||
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||
headBlock := rawdb.ReadHeadBlock(chaindb)
|
||||
|
||||
if headBlock == nil {
|
||||
log.Error("Failed to load head block")
|
||||
return errors.New("no head block")
|
||||
}
|
||||
|
||||
if ctx.NArg() > 1 {
|
||||
log.Error("Too many arguments given")
|
||||
return errors.New("too many arguments")
|
||||
}
|
||||
|
||||
var (
|
||||
rootC common.Hash
|
||||
err error
|
||||
)
|
||||
|
||||
if ctx.NArg() == 1 {
|
||||
rootC, err = parseRoot(ctx.Args().First())
|
||||
if err != nil {
|
||||
log.Error("Failed to resolve state root", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info("Rebuilding the tree", "root", rootC)
|
||||
} else {
|
||||
rootC = headBlock.Root()
|
||||
|
|
@ -144,7 +152,9 @@ func verifyVerkle(ctx *cli.Context) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -155,6 +165,7 @@ func verifyVerkle(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
log.Info("Tree was rebuilt from the database")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -163,27 +174,34 @@ func expandVerkle(ctx *cli.Context) error {
|
|||
defer stack.Close()
|
||||
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack, true)
|
||||
|
||||
var (
|
||||
rootC common.Hash
|
||||
keylist [][]byte
|
||||
err error
|
||||
)
|
||||
|
||||
if ctx.NArg() >= 2 {
|
||||
rootC, err = parseRoot(ctx.Args().First())
|
||||
if err != nil {
|
||||
log.Error("Failed to resolve state root", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
keylist = make([][]byte, 0, ctx.Args().Len()-1)
|
||||
|
||||
args := ctx.Args().Slice()
|
||||
for i := range args[1:] {
|
||||
key, err := hex.DecodeString(args[i+1])
|
||||
log.Info("decoded key", "arg", args[i+1], "key", key)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decoding key #%d: %w", i+1, err)
|
||||
}
|
||||
|
||||
keylist = append(keylist, key)
|
||||
}
|
||||
|
||||
log.Info("Rebuilding the tree", "root", rootC)
|
||||
} else {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
root, err := verkle.ParseNode(serializedRoot, 0, rootC[:])
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -208,5 +228,6 @@ func expandVerkle(ctx *cli.Context) error {
|
|||
} else {
|
||||
log.Info("Tree was dumped to file", "file", "dump.dot")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ func monitorFreeDiskSpace(sigc chan os.Signal, path string, freeDiskSpaceCritica
|
|||
} 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)
|
||||
}
|
||||
|
||||
time.Sleep(30 * time.Second)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1037,6 +1037,7 @@ func MakeDataDir(ctx *cli.Context) string {
|
|||
if ctx.Bool(GoerliFlag.Name) {
|
||||
return filepath.Join(path, "goerli")
|
||||
}
|
||||
|
||||
if ctx.Bool(SepoliaFlag.Name) {
|
||||
return filepath.Join(path, "sepolia")
|
||||
}
|
||||
|
|
@ -1140,6 +1141,7 @@ func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
|
|||
if ctx.IsSet(ListenPortFlag.Name) {
|
||||
cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name))
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
cfg.HTTPPathPrefix = ctx.String(HTTPPathPrefixFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
cfg.GraphQLCors = SplitAndTrim(ctx.String(GraphQLCORSDomainFlag.Name))
|
||||
}
|
||||
|
||||
if ctx.IsSet(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)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
cfg.LightServ = ctx.Int(LightServeFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(LightIngressFlag.Name) {
|
||||
cfg.LightIngress = ctx.Int(LightIngressFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(LightEgressFlag.Name) {
|
||||
cfg.LightEgress = ctx.Int(LightEgressFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(LightMaxPeersFlag.Name) {
|
||||
cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(UltraLightServersFlag.Name) {
|
||||
cfg.UltraLightServers = strings.Split(ctx.String(UltraLightServersFlag.Name), ",")
|
||||
}
|
||||
|
||||
if ctx.IsSet(UltraLightFractionFlag.Name) {
|
||||
cfg.UltraLightFraction = ctx.Int(UltraLightFractionFlag.Name)
|
||||
}
|
||||
|
||||
if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 {
|
||||
log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", ethconfig.Defaults.UltraLightFraction)
|
||||
cfg.UltraLightFraction = ethconfig.Defaults.UltraLightFraction
|
||||
}
|
||||
|
||||
if ctx.IsSet(UltraLightOnlyAnnounceFlag.Name) {
|
||||
cfg.UltraLightOnlyAnnounce = ctx.Bool(UltraLightOnlyAnnounceFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(LightNoPruneFlag.Name) {
|
||||
cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
return
|
||||
}
|
||||
|
||||
addr := ctx.String(MinerEtherbaseFlag.Name)
|
||||
|
||||
if strings.HasPrefix(addr, "0x") || strings.HasPrefix(addr, "0X") {
|
||||
addr = addr[2:]
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(addr)
|
||||
|
||||
if err != nil || len(b) != common.AddressLength {
|
||||
Fatalf("-%s: invalid etherbase address %q", MinerEtherbaseFlag.Name, addr)
|
||||
return
|
||||
}
|
||||
|
||||
cfg.Miner.Etherbase = common.BytesToAddress(b)
|
||||
}
|
||||
|
||||
|
|
@ -1373,6 +1392,7 @@ func MakePasswordList(ctx *cli.Context) []string {
|
|||
if path == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
text, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
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) {
|
||||
cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(NoDiscoverFlag.Name) || lightClient {
|
||||
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
|
||||
// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
|
||||
forceV5Discovery := (lightClient || lightServer) && !ctx.Bool(NoDiscoverFlag.Name)
|
||||
|
||||
if ctx.IsSet(DiscoveryV5Flag.Name) {
|
||||
cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name)
|
||||
} else if forceV5Discovery {
|
||||
|
|
@ -1484,26 +1506,33 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
|
|||
if ctx.IsSet(KeyStoreDirFlag.Name) {
|
||||
cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(DeveloperFlag.Name) {
|
||||
cfg.UseLightweightKDF = true
|
||||
}
|
||||
|
||||
if ctx.IsSet(LightKDFFlag.Name) {
|
||||
cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB {
|
||||
log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable")
|
||||
}
|
||||
|
||||
if ctx.IsSet(USBFlag.Name) {
|
||||
cfg.USB = ctx.Bool(USBFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(InsecureUnlockAllowedFlag.Name) {
|
||||
cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(DBEngineFlag.Name) {
|
||||
dbEngine := ctx.String(DBEngineFlag.Name)
|
||||
if dbEngine != "leveldb" && dbEngine != "pebble" {
|
||||
Fatalf("Invalid choice for db.engine '%s', allowed 'leveldb' or 'pebble'", dbEngine)
|
||||
}
|
||||
|
||||
log.Info(fmt.Sprintf("Using %s as db engine", dbEngine))
|
||||
cfg.DBEngine = dbEngine
|
||||
}
|
||||
|
|
@ -1517,10 +1546,12 @@ func setSmartCard(ctx *cli.Context, cfg *node.Config) {
|
|||
}
|
||||
// Sanity check that the smartcard path is valid
|
||||
fi, err := os.Stat(path)
|
||||
|
||||
if err != nil {
|
||||
log.Info("Smartcard socket not found, disabling", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if fi.Mode()&os.ModeType != os.ModeSocket {
|
||||
log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
|
||||
return
|
||||
|
|
@ -1548,15 +1579,19 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
|
|||
if light {
|
||||
*cfg = ethconfig.LightClientGPO
|
||||
}
|
||||
|
||||
if ctx.IsSet(GpoBlocksFlag.Name) {
|
||||
cfg.Blocks = ctx.Int(GpoBlocksFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(GpoPercentileFlag.Name) {
|
||||
cfg.Percentile = ctx.Int(GpoPercentileFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(GpoMaxGasPriceFlag.Name) {
|
||||
cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name))
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolJournalFlag.Name) {
|
||||
cfg.Journal = ctx.String(TxPoolJournalFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolRejournalFlag.Name) {
|
||||
cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolPriceLimitFlag.Name) {
|
||||
cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolPriceBumpFlag.Name) {
|
||||
cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolAccountSlotsFlag.Name) {
|
||||
cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) {
|
||||
cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolAccountQueueFlag.Name) {
|
||||
cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxPoolGlobalQueueFlag.Name) {
|
||||
cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(EthashDatasetDirFlag.Name) {
|
||||
cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(EthashCachesInMemoryFlag.Name) {
|
||||
cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(EthashCachesOnDiskFlag.Name) {
|
||||
cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(EthashCachesLockMmapFlag.Name) {
|
||||
cfg.Ethash.CachesLockMmap = ctx.Bool(EthashCachesLockMmapFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) {
|
||||
cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) {
|
||||
cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(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) {
|
||||
cfg.Notify = strings.Split(ctx.String(MinerNotifyFlag.Name), ",")
|
||||
}
|
||||
|
||||
cfg.NotifyFull = ctx.Bool(MinerNotifyFullFlag.Name)
|
||||
|
||||
if ctx.IsSet(MinerExtraDataFlag.Name) {
|
||||
cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name))
|
||||
}
|
||||
|
||||
if ctx.IsSet(MinerGasLimitFlag.Name) {
|
||||
cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(MinerGasPriceFlag.Name) {
|
||||
cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(MinerRecommitIntervalFlag.Name) {
|
||||
cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(MinerNoVerifyFlag.Name) {
|
||||
cfg.Noverify = ctx.Bool(MinerNoVerifyFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(MinerNewPayloadTimeout.Name) {
|
||||
cfg.NewPayloadTimeout = ctx.Duration(MinerNewPayloadTimeout.Name)
|
||||
}
|
||||
|
|
@ -1662,12 +1721,15 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
|||
if requiredBlocks == "" {
|
||||
if ctx.IsSet(LegacyWhitelistFlag.Name) {
|
||||
log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks")
|
||||
|
||||
requiredBlocks = ctx.String(LegacyWhitelistFlag.Name)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
cfg.RequiredBlocks = make(map[uint64]common.Hash)
|
||||
|
||||
for _, entry := range strings.Split(requiredBlocks, ",") {
|
||||
parts := strings.Split(entry, "=")
|
||||
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 {
|
||||
Fatalf("Invalid required block hash %s: %v", parts[1], err)
|
||||
}
|
||||
|
||||
cfg.RequiredBlocks[number] = hash
|
||||
}
|
||||
}
|
||||
|
|
@ -1736,9 +1799,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
ctx.Set(TxLookupLimitFlag.Name, "0")
|
||||
log.Warn("Disable transaction unindexing for archive node")
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
setEtherbase(ctx, cfg)
|
||||
setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
|
||||
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
|
||||
}
|
||||
allowance := int(mem.Total / 1024 / 1024 / 3)
|
||||
|
||||
if cache := ctx.Int(CacheFlag.Name); cache > allowance {
|
||||
log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", 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) {
|
||||
cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
|
||||
}
|
||||
|
||||
if ctx.IsSet(NetworkIdFlag.Name) {
|
||||
cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) {
|
||||
cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
||||
}
|
||||
|
||||
cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
|
||||
|
||||
if ctx.IsSet(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" {
|
||||
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(GCModeFlag.Name) {
|
||||
cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive"
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheNoPrefetchFlag.Name) {
|
||||
cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name)
|
||||
}
|
||||
// Read the value from the flag no matter if it's set or not.
|
||||
cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name)
|
||||
|
||||
if cfg.NoPruning && !cfg.Preimages {
|
||||
cfg.Preimages = true
|
||||
log.Info("Enabling recording of key preimages since archive mode is used")
|
||||
}
|
||||
|
||||
if ctx.IsSet(TxLookupLimitFlag.Name) {
|
||||
cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
|
||||
cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheTrieJournalFlag.Name) {
|
||||
cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheTrieRejournalFlag.Name) {
|
||||
cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
||||
cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
|
||||
cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheLogSizeFlag.Name) {
|
||||
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
|
||||
}
|
||||
|
||||
if !ctx.Bool(SnapshotFlag.Name) {
|
||||
// If snap-sync is requested, this flag is also required
|
||||
if cfg.SyncMode == downloader.SnapSync {
|
||||
|
|
@ -1826,9 +1907,11 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
cfg.SnapshotCache = 0 // Disabled
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.IsSet(DocRootFlag.Name) {
|
||||
cfg.DocRoot = ctx.String(DocRootFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(VMEnableDebugFlag.Name) {
|
||||
// TODO(fjl): force-enable this in --dev mode
|
||||
cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
|
||||
|
|
@ -1842,12 +1925,15 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
} else {
|
||||
log.Info("Global gas cap disabled")
|
||||
}
|
||||
|
||||
if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) {
|
||||
cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) {
|
||||
cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(NoDiscoverFlag.Name) {
|
||||
cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{}
|
||||
} 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 {
|
||||
ks = keystores[0].(*keystore.KeyStore)
|
||||
}
|
||||
|
||||
if ks == nil {
|
||||
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
|
||||
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
|
||||
|
||||
if ctx.IsSet(DataDirFlag.Name) {
|
||||
// If datadir doesn't exist we need to open db in write-mode
|
||||
// so leveldb can create files.
|
||||
|
|
@ -1944,6 +2032,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
}
|
||||
chaindb.Close()
|
||||
}
|
||||
|
||||
if !ctx.IsSet(MinerGasPriceFlag.Name) {
|
||||
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)
|
||||
}
|
||||
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
|
||||
|
||||
if err := lescatalyst.Register(stack, backend); err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if err := ethcatalyst.Register(stack, backend); err != nil {
|
||||
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{
|
||||
LogCacheSize: ethcfg.FilterLogCacheSize,
|
||||
})
|
||||
|
||||
stack.RegisterAPIs([]rpc.API{{
|
||||
Namespace: "eth",
|
||||
Service: filters.NewFilterAPI(filterSystem, isLightClient, ethconfig.Defaults.BorLogs),
|
||||
}})
|
||||
|
||||
return filterSystem
|
||||
}
|
||||
|
||||
|
|
@ -2036,11 +2129,15 @@ func RegisterFullSyncTester(stack *node.Node, eth *eth.Ethereum, path string) {
|
|||
if err != nil {
|
||||
Fatalf("Failed to read block file: %v", err)
|
||||
}
|
||||
|
||||
rlpBlob, err := hexutil.Decode(string(bytes.TrimRight(blob, "\r\n")))
|
||||
|
||||
if err != nil {
|
||||
Fatalf("Failed to decode block blob: %v", err)
|
||||
}
|
||||
|
||||
var block types.Block
|
||||
|
||||
if err := rlp.DecodeBytes(rlpBlob, &block); err != nil {
|
||||
Fatalf("Failed to decode block: %v", err)
|
||||
}
|
||||
|
|
@ -2135,13 +2232,16 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
|
|||
err error
|
||||
chainDb ethdb.Database
|
||||
)
|
||||
|
||||
switch {
|
||||
case ctx.IsSet(RemoteDBFlag.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))
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
chainDb = remotedb.New(client)
|
||||
case ctx.String(SyncModeFlag.Name) == "light":
|
||||
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
|
||||
|
|
@ -2161,6 +2261,7 @@ func IsNetworkPreset(ctx *cli.Context) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -2168,23 +2269,30 @@ func DialRPCWithHeaders(endpoint string, headers []string) (*rpc.Client, error)
|
|||
if endpoint == "" {
|
||||
return nil, errors.New("endpoint must be specified")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(endpoint, "rpc:") || strings.HasPrefix(endpoint, "ipc:") {
|
||||
// Backwards compatibility with geth < 1.5 which required
|
||||
// these prefixes.
|
||||
endpoint = endpoint[4:]
|
||||
}
|
||||
|
||||
var opts []rpc.ClientOption
|
||||
|
||||
if len(headers) > 0 {
|
||||
var customHeaders = make(http.Header)
|
||||
|
||||
for _, h := range headers {
|
||||
kv := strings.Split(h, ":")
|
||||
if len(kv) != 2 {
|
||||
return nil, fmt.Errorf("invalid http header directive: %q", h)
|
||||
}
|
||||
|
||||
customHeaders.Add(kv[0], kv[1])
|
||||
}
|
||||
|
||||
opts = append(opts, rpc.WithHeaders(customHeaders))
|
||||
}
|
||||
|
||||
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)
|
||||
chainDb = MakeChainDatabase(ctx, stack, readonly)
|
||||
)
|
||||
|
||||
config, _, err := core.SetupGenesisBlock(chainDb, trie.NewDatabase(chainDb), gspec)
|
||||
if err != nil {
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
|
||||
cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec)
|
||||
if err != nil {
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
|
||||
ethashConfig := ethconfig.Defaults.Ethash
|
||||
|
||||
if ctx.Bool(FakePoWFlag.Name) {
|
||||
ethashConfig.PowMode = ethash.ModeFake
|
||||
}
|
||||
|
||||
configs := ðconfig.Config{
|
||||
Genesis: gspec,
|
||||
HeimdallURL: ctx.String(HeimdallURLFlag.Name),
|
||||
|
|
@ -2232,6 +2345,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
|||
}
|
||||
_ = CreateBorEthereum(configs)
|
||||
engine := ethconfig.CreateConsensusEngine(stack, config, configs, ðashConfig, cliqueConfig, nil, false, chainDb, nil)
|
||||
|
||||
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
|
||||
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
|
||||
log.Info("Enabling recording of key preimages since archive mode is used")
|
||||
}
|
||||
|
||||
if !ctx.Bool(SnapshotFlag.Name) {
|
||||
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) {
|
||||
cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
|
||||
}
|
||||
|
||||
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
|
||||
cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
|
||||
}
|
||||
|
||||
vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}
|
||||
|
||||
// Disable transaction indexing/unindexing by default.
|
||||
|
|
|
|||
|
|
@ -54,5 +54,6 @@ func showDeprecated(*cli.Context) error {
|
|||
fmt.Println(flag.String())
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ func (c *Console) initWeb3(bridge *bridge) error {
|
|||
if err := c.jsre.Compile("bignumber.js", deps.BigNumberJS); err != nil {
|
||||
return fmt.Errorf("bignumber.js: %v", err)
|
||||
}
|
||||
|
||||
if err := c.jsre.Compile("web3.js", deps.Web3JS); err != nil {
|
||||
return fmt.Errorf("web3.js: %v", err)
|
||||
}
|
||||
|
|
@ -208,6 +209,7 @@ func (c *Console) initExtensions() error {
|
|||
if err != nil {
|
||||
if rpcErr, ok := err.(rpc.Error); ok && rpcErr.ErrorCode() == methodNotFound {
|
||||
log.Warn("Server does not support method rpc_modules, using default API list.")
|
||||
|
||||
apis = defaultAPIs
|
||||
} else {
|
||||
return err
|
||||
|
|
@ -260,6 +262,7 @@ func (c *Console) initPersonal(vm *goja.Runtime, bridge *bridge) {
|
|||
if personal == nil || c.prompter == nil {
|
||||
return
|
||||
}
|
||||
|
||||
log.Warn("Enabling deprecated personal namespace")
|
||||
jeth := vm.NewObject()
|
||||
vm.Set("jeth", jeth)
|
||||
|
|
|
|||
|
|
@ -173,6 +173,7 @@ func genUncles(i int, gen *BlockGen) {
|
|||
func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||
// Create the database in memory or in a temporary directory.
|
||||
var db ethdb.Database
|
||||
|
||||
var err error
|
||||
if !disk {
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
|
|
@ -264,6 +265,7 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
|
|||
if n == 0 {
|
||||
rawdb.WriteChainConfig(db, hash, params.AllEthashProtocolChanges)
|
||||
}
|
||||
|
||||
rawdb.WriteHeadHeaderHash(db, hash)
|
||||
|
||||
if full || n == 0 {
|
||||
|
|
@ -307,6 +309,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
|||
if err != nil {
|
||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||
}
|
||||
|
||||
chain, err := NewBlockChain(db, &cacheConfig, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
b.Fatalf("error creating chain: %v", err)
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
|||
if block.Withdrawals() == nil {
|
||||
return fmt.Errorf("missing withdrawals in block body")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
|||
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||
config = *params.AllCliqueProtocolChanges
|
||||
)
|
||||
|
||||
engine = beacon.New(clique.New(params.AllCliqueProtocolChanges.Clique, rawdb.NewMemoryDatabase()))
|
||||
gspec = &Genesis{
|
||||
Config: &config,
|
||||
|
|
@ -112,6 +113,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
|||
|
||||
td := 0
|
||||
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
|
||||
|
||||
for i, block := range blocks {
|
||||
header := block.Header()
|
||||
if i > 0 {
|
||||
|
|
@ -127,6 +129,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
|
|||
// calculate td
|
||||
td += int(block.Difficulty().Uint64())
|
||||
}
|
||||
|
||||
preBlocks = blocks
|
||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
|
||||
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())
|
||||
seals = append(seals, true)
|
||||
}
|
||||
|
||||
_, results := engine.VerifyHeaders(chain, headers, seals)
|
||||
for i := 0; i < len(headers); i++ {
|
||||
select {
|
||||
|
|
|
|||
|
|
@ -274,11 +274,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
|
||||
return nil, genesisErr
|
||||
}
|
||||
|
||||
log.Info("")
|
||||
log.Info(strings.Repeat("-", 153))
|
||||
|
||||
for _, line := range strings.Split(chainConfig.Description(), "\n") {
|
||||
log.Info(line)
|
||||
}
|
||||
|
||||
log.Info(strings.Repeat("-", 153))
|
||||
log.Info("")
|
||||
|
||||
|
|
@ -381,6 +384,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
snapBlock := bc.CurrentSnapBlock()
|
||||
if snapBlock != nil && snapBlock.Number.Uint64() < frozen-1 {
|
||||
needRewind = true
|
||||
|
||||
if snapBlock.Number.Uint64() < low || low == 0 {
|
||||
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)
|
||||
recover = true
|
||||
}
|
||||
|
||||
snapconfig := snapshot.Config{
|
||||
CacheSize: bc.cacheConfig.SnapshotLimit,
|
||||
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.
|
||||
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
|
||||
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
|
||||
|
||||
if compat.RewindToTime > 0 {
|
||||
bc.SetHeadWithTimestamp(compat.RewindToTime)
|
||||
} else {
|
||||
bc.SetHead(compat.RewindToBlock)
|
||||
}
|
||||
|
||||
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
|
||||
}
|
||||
// Start tx indexer/unindexer if required.
|
||||
|
|
@ -466,8 +473,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||
bc.txLookupLimit = *txLookupLimit
|
||||
|
||||
bc.wg.Add(1)
|
||||
|
||||
go bc.maintainTxIndex()
|
||||
}
|
||||
|
||||
return bc, nil
|
||||
}
|
||||
|
||||
|
|
@ -486,6 +495,7 @@ func NewParallelBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis
|
|||
Preimages: cacheConfig.Preimages,
|
||||
})
|
||||
chainConfig, _, genesisErr := SetupGenesisBlockWithOverride(db, triedb, genesis, overrides)
|
||||
|
||||
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
|
||||
return nil, genesisErr
|
||||
}
|
||||
|
|
@ -611,6 +621,7 @@ func (bc *BlockChain) loadLastState() error {
|
|||
headHeader = header
|
||||
}
|
||||
}
|
||||
|
||||
bc.hc.SetCurrentHeader(headHeader)
|
||||
|
||||
// Restore the last known head fast block
|
||||
|
|
@ -643,14 +654,18 @@ func (bc *BlockChain) loadLastState() error {
|
|||
headerTd = bc.GetTd(headHeader.Hash(), headHeader.Number.Uint64())
|
||||
blockTd = bc.GetTd(headBlock.Hash(), headBlock.NumberU64())
|
||||
)
|
||||
|
||||
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 block", "number", headBlock.Number(), "hash", headBlock.Hash(), "td", blockTd, "age", common.PrettyAge(time.Unix(int64(headBlock.Time()), 0)))
|
||||
|
||||
if headBlock.Hash() != currentSnapBlock.Hash() {
|
||||
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)))
|
||||
}
|
||||
|
||||
if currentFinalBlock != nil {
|
||||
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)))
|
||||
|
|
@ -671,6 +686,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
|||
// Send chain head event to update the transaction pool
|
||||
header := bc.CurrentBlock()
|
||||
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
||||
|
||||
if block == nil {
|
||||
// This should never happen. In practice, previsouly currentBlock
|
||||
// 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())
|
||||
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
||||
}
|
||||
|
||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -693,6 +711,7 @@ func (bc *BlockChain) SetHeadWithTimestamp(timestamp uint64) error {
|
|||
// Send chain head event to update the transaction pool
|
||||
header := bc.CurrentBlock()
|
||||
block := bc.GetBlock(header.Hash(), header.Number.Uint64())
|
||||
|
||||
if block == nil {
|
||||
// This should never happen. In practice, previsouly currentBlock
|
||||
// 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())
|
||||
return fmt.Errorf("current block missing: #%d [%x..]", header.Number, header.Hash().Bytes()[:4])
|
||||
}
|
||||
|
||||
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFinalized sets the finalized block.
|
||||
func (bc *BlockChain) SetFinalized(header *types.Header) {
|
||||
bc.currentFinalBlock.Store(header)
|
||||
|
||||
if header != nil {
|
||||
rawdb.WriteFinalizedBlockHash(bc.db, header.Hash())
|
||||
headFinalizedBlockGauge.Update(int64(header.Number.Uint64()))
|
||||
|
|
@ -719,6 +741,7 @@ func (bc *BlockChain) SetFinalized(header *types.Header) {
|
|||
// SetSafe sets the safe block.
|
||||
func (bc *BlockChain) SetSafe(header *types.Header) {
|
||||
bc.currentSafeBlock.Store(header)
|
||||
|
||||
if header != nil {
|
||||
headSafeBlockGauge.Update(int64(header.Number.Uint64()))
|
||||
} else {
|
||||
|
|
@ -824,15 +847,17 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
|||
if newHeadSnapBlock == nil {
|
||||
newHeadSnapBlock = bc.genesisBlock
|
||||
}
|
||||
|
||||
rawdb.WriteHeadFastBlockHash(db, newHeadSnapBlock.Hash())
|
||||
|
||||
// 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
|
||||
// to low, so it's safe the update in-memory markers directly.
|
||||
bc.currentSnapBlock.Store(newHeadSnapBlock.Header())
|
||||
headFastBlockGauge.Update(int64(newHeadSnapBlock.NumberU64()))
|
||||
}
|
||||
|
||||
var (
|
||||
headHeader = bc.CurrentBlock()
|
||||
headNumber = headHeader.Number.Uint64()
|
||||
|
|
@ -844,6 +869,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
|
|||
if headNumber+1 < frozen {
|
||||
wipe = pivot == nil || headNumber >= *pivot
|
||||
}
|
||||
|
||||
return headHeader, wipe // Only force wipe if full synced
|
||||
}
|
||||
// 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")
|
||||
bc.SetSafe(nil)
|
||||
}
|
||||
|
||||
if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() {
|
||||
log.Error("SetHead invalidated finalized block")
|
||||
bc.SetFinalized(nil)
|
||||
|
|
@ -915,7 +942,9 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
|
|||
if block == nil {
|
||||
return fmt.Errorf("non existent block [%x..]", hash[:4])
|
||||
}
|
||||
|
||||
root := block.Root()
|
||||
|
||||
if !bc.HasState(root) {
|
||||
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() {
|
||||
return errChainStopped
|
||||
}
|
||||
|
||||
bc.currentBlock.Store(block.Header())
|
||||
headBlockGauge.Update(int64(block.NumberU64()))
|
||||
bc.chainmu.Unlock()
|
||||
|
|
@ -995,9 +1025,11 @@ func (bc *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
|
|||
if block == nil {
|
||||
return fmt.Errorf("export failed on #%d: not found", nr)
|
||||
}
|
||||
|
||||
if nr > first && block.ParentHash() != parentHash {
|
||||
return fmt.Errorf("export failed: chain reorg during export")
|
||||
}
|
||||
|
||||
parentHash = block.Hash()
|
||||
if err := block.EncodeRLP(w); err != nil {
|
||||
return err
|
||||
|
|
@ -1094,6 +1126,7 @@ func (bc *BlockChain) Stop() {
|
|||
recent := bc.GetBlockByNumber(number - offset)
|
||||
|
||||
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 {
|
||||
log.Error("Failed to commit recent state trie", "err", err)
|
||||
}
|
||||
|
|
@ -1101,6 +1134,7 @@ func (bc *BlockChain) Stop() {
|
|||
}
|
||||
if snapBase != (common.Hash{}) {
|
||||
log.Info("Writing snapshot state to disk", "root", snapBase)
|
||||
|
||||
if err := triedb.Commit(snapBase, true); err != nil {
|
||||
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 {
|
||||
context = append(context, []interface{}{"ignored", stats.ignored}...)
|
||||
}
|
||||
|
||||
log.Debug("Imported new block receipts", context...)
|
||||
|
||||
return 0, nil
|
||||
|
|
@ -1565,6 +1600,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
nodes, imgs = bc.triedb.Size()
|
||||
limit = common.StorageSize(bc.cacheConfig.TrieDirtyLimit) * 1024 * 1024
|
||||
)
|
||||
|
||||
if nodes > limit || imgs > 4*1024*1024 {
|
||||
bc.triedb.Cap(limit - ethdb.IdealBatchSize)
|
||||
}
|
||||
|
|
@ -1597,6 +1633,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
|||
bc.triegc.Push(root, number)
|
||||
break
|
||||
}
|
||||
|
||||
bc.triedb.Dereference(root)
|
||||
}
|
||||
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)
|
||||
|
||||
blockPrefetchExecuteTimer.Update(time.Since(start))
|
||||
|
||||
if followupInterrupt.Load() {
|
||||
blockPrefetchInterruptMeter.Mark(1)
|
||||
}
|
||||
|
|
@ -2056,6 +2094,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
|||
followupInterrupt.Store(true)
|
||||
return it.index, err
|
||||
}
|
||||
|
||||
vtime := time.Since(vstart)
|
||||
proctime := time.Since(start) // processing + validation
|
||||
|
||||
|
|
@ -2086,6 +2125,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
|||
} else {
|
||||
status, err = bc.writeBlockAndSetHead(context.Background(), block, receipts, logs, statedb, false)
|
||||
}
|
||||
|
||||
followupInterrupt.Store(true)
|
||||
if err != nil {
|
||||
return it.index, err
|
||||
|
|
@ -2353,6 +2393,7 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error)
|
|||
return b.ParentHash(), err
|
||||
}
|
||||
}
|
||||
|
||||
return block.Hash(), nil
|
||||
}
|
||||
|
||||
|
|
@ -2396,10 +2437,13 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
|||
deletedTxs []common.Hash
|
||||
addedTxs []common.Hash
|
||||
)
|
||||
|
||||
oldBlock := bc.GetBlock(oldHead.Hash(), oldHead.Number.Uint64())
|
||||
|
||||
if oldBlock == nil {
|
||||
return errors.New("current head block missing")
|
||||
}
|
||||
|
||||
newBlock := newHead
|
||||
|
||||
// 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
|
||||
for ; oldBlock != nil && oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = bc.GetBlock(oldBlock.ParentHash(), oldBlock.NumberU64()-1) {
|
||||
oldChain = append(oldChain, oldBlock)
|
||||
|
||||
for _, tx := range oldBlock.Transactions() {
|
||||
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
|
||||
oldChain = append(oldChain, oldBlock)
|
||||
|
||||
for _, tx := range oldBlock.Transactions() {
|
||||
deletedTxs = append(deletedTxs, tx.Hash())
|
||||
}
|
||||
|
|
@ -2551,6 +2597,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error {
|
|||
|
||||
// Deleted logs + blocks:
|
||||
var deletedLogs []*types.Log
|
||||
|
||||
for i := len(oldChain) - 1; i >= 0; i-- {
|
||||
// Also send event for blocks removed from the canon chain.
|
||||
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 {
|
||||
deletedLogs = append(deletedLogs, logs...)
|
||||
}
|
||||
|
||||
if len(deletedLogs) > 512 {
|
||||
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
||||
deletedLogs = nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(deletedLogs) > 0 {
|
||||
bc.rmLogsFeed.Send(RemovedLogsEvent{deletedLogs})
|
||||
}
|
||||
|
||||
// New logs:
|
||||
var rebirthLogs []*types.Log
|
||||
|
||||
for i := len(newChain) - 1; i >= 1; i-- {
|
||||
if logs := bc.collectLogs(newChain[i], false); len(logs) > 0 {
|
||||
rebirthLogs = append(rebirthLogs, logs...)
|
||||
}
|
||||
|
||||
if len(rebirthLogs) > 512 {
|
||||
bc.logsFeed.Send(rebirthLogs)
|
||||
rebirthLogs = nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(rebirthLogs) > 0 {
|
||||
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 {
|
||||
return latestValidHash, err
|
||||
}
|
||||
|
||||
log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash())
|
||||
}
|
||||
// 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)}...)
|
||||
}
|
||||
log.Info("Chain head was updated", context...)
|
||||
|
||||
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 {
|
||||
from = head - bc.txLookupLimit + 1
|
||||
}
|
||||
|
||||
rawdb.IndexTransactions(bc.db, from, head+1, bc.quit)
|
||||
|
||||
return
|
||||
}
|
||||
// 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 {
|
||||
end = head + 1
|
||||
}
|
||||
|
||||
rawdb.IndexTransactions(bc.db, 0, end, bc.quit)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
// 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(),
|
||||
receipt.Status, receipt.TxHash.Hex(), receipt.Logs, receipt.Bloom, receipt.PostState)
|
||||
}
|
||||
|
||||
version, vcs := version.Info()
|
||||
platform := fmt.Sprintf("%s %s %s %s", version, runtime.Version(), runtime.GOARCH, runtime.GOOS)
|
||||
|
||||
if vcs != "" {
|
||||
vcs = fmt.Sprintf("\nVCS: %s", vcs)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`
|
||||
########## BAD BLOCK #########
|
||||
Block: %v (%#x)
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
|
|||
if bc.blockCache.Contains(hash) {
|
||||
return true
|
||||
}
|
||||
|
||||
if !bc.HasHeader(hash, number) {
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,11 +69,13 @@ func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *G
|
|||
// Full block-chain requested
|
||||
genDb, blocks := makeBlockChainWithGenesis(genesis, n, engine, canonicalSeed)
|
||||
_, err := blockchain.InsertChain(blocks)
|
||||
|
||||
return genDb, genesis, blockchain, err
|
||||
}
|
||||
// Header-only chain requested
|
||||
genDb, headers := makeHeaderChainWithGenesis(genesis, n, engine, canonicalSeed)
|
||||
_, err := blockchain.InsertHeaderChain(headers, 1)
|
||||
|
||||
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 {
|
||||
t.Fatalf("failed to insert forking chain: %v", err)
|
||||
}
|
||||
|
||||
if blockchain2.CurrentBlock().Number.Uint64() != blockChainB[len(blockChainB)-1].NumberU64() {
|
||||
t.Fatalf("failed to reorg to the given chain")
|
||||
}
|
||||
|
|
@ -767,6 +770,7 @@ func TestFastVsFullChains(t *testing.T) {
|
|||
}
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
)
|
||||
|
||||
_, blocks, receipts := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 1024, func(i int, block *BlockGen) {
|
||||
block.SetCoinbase(common.Address{0x00})
|
||||
|
||||
|
|
@ -902,6 +906,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create temp freezer db: %v", err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
// Configure a subchain to roll back
|
||||
|
|
@ -914,6 +919,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
|||
if num := chain.CurrentBlock().Number.Uint64(); num != block {
|
||||
t.Errorf("%s head block mismatch: have #%v, want #%v", kind, num, block)
|
||||
}
|
||||
|
||||
if num := chain.CurrentSnapBlock().Number.Uint64(); 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)
|
||||
blockchain.SubscribeRemovedLogsEvent(rmLogsCh)
|
||||
|
||||
_, chain, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 2, func(i int, gen *BlockGen) {
|
||||
if i == 1 {
|
||||
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 {
|
||||
t.Fatalf("failed to insert chain: %v", err)
|
||||
}
|
||||
|
||||
checkLogEvents(t, newLogCh, rmLogsCh, 10, 0)
|
||||
|
||||
// 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 {
|
||||
t.Fatalf("failed to insert forked chain: %v", err)
|
||||
}
|
||||
|
||||
checkLogEvents(t, newLogCh, rmLogsCh, 10, 10)
|
||||
|
||||
// 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 {
|
||||
t.Fatalf("failed to insert forked chain: %v", err)
|
||||
}
|
||||
|
||||
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) {
|
||||
t.Helper()
|
||||
|
||||
var (
|
||||
countNew int
|
||||
countRm int
|
||||
|
|
@ -1297,25 +1308,31 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
|
|||
for len(logsCh) > 0 {
|
||||
x := <-logsCh
|
||||
countNew += len(x)
|
||||
|
||||
for _, log := range x {
|
||||
// We expect added logs to be in ascending order: 0:0, 0:1, 1:0 ...
|
||||
have := 100*int(log.BlockNumber) + int(log.TxIndex)
|
||||
if have < prev {
|
||||
t.Fatalf("Expected new logs to arrive in ascending order (%d < %d)", have, prev)
|
||||
}
|
||||
|
||||
prev = have
|
||||
}
|
||||
}
|
||||
|
||||
prev = 0
|
||||
|
||||
for len(rmLogsCh) > 0 {
|
||||
x := <-rmLogsCh
|
||||
countRm += len(x.Logs)
|
||||
|
||||
for _, log := range x.Logs {
|
||||
// We expect removed logs to be in ascending order: 0:0, 0:1, 1:0 ...
|
||||
have := 100*int(log.BlockNumber) + int(log.TxIndex)
|
||||
if have < prev {
|
||||
t.Fatalf("Expected removed logs to arrive in ascending order (%d < %d)", have, prev)
|
||||
}
|
||||
|
||||
prev = have
|
||||
}
|
||||
}
|
||||
|
|
@ -1323,6 +1340,7 @@ func checkLogEvents(t *testing.T, logsCh <-chan []*types.Log, rmLogsCh <-chan Re
|
|||
if countNew != wantNew {
|
||||
t.Fatalf("wrong number of log events: got %d, want %d", countNew, wantNew)
|
||||
}
|
||||
|
||||
if 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)
|
||||
)
|
||||
|
||||
blockchain, _ := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
||||
defer blockchain.Stop()
|
||||
|
||||
|
|
@ -1471,6 +1490,7 @@ func TestEIP155Transition(t *testing.T) {
|
|||
Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
|
||||
}
|
||||
)
|
||||
|
||||
genDb, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 4, func(i int, block *BlockGen) {
|
||||
var (
|
||||
tx *types.Transaction
|
||||
|
|
@ -1582,6 +1602,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
|||
Alloc: GenesisAlloc{address: {Balance: funds}},
|
||||
}
|
||||
)
|
||||
|
||||
_, blocks, _ := GenerateChainWithGenesis(gspec, ethash.NewFaker(), 3, func(i int, block *BlockGen) {
|
||||
var (
|
||||
tx *types.Transaction
|
||||
|
|
@ -1650,6 +1671,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
|
|||
if i > 0 {
|
||||
parent = blocks[i-1]
|
||||
}
|
||||
|
||||
fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
|
||||
forks[i] = fork[0]
|
||||
}
|
||||
|
|
@ -1659,6 +1681,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
for i := 0; i < len(blocks); i++ {
|
||||
|
|
@ -1695,6 +1718,7 @@ func TestTrieForkGC(t *testing.T) {
|
|||
if i > 0 {
|
||||
parent = blocks[i-1]
|
||||
}
|
||||
|
||||
fork, _ := GenerateChain(genesis.Config, parent, engine, genDb, 1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
|
||||
forks[i] = fork[0]
|
||||
}
|
||||
|
|
@ -1703,6 +1727,7 @@ func TestTrieForkGC(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
for i := 0; i < len(blocks); i++ {
|
||||
|
|
@ -1741,6 +1766,7 @@ func TestLargeReorgTrieGC(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if _, err := chain.InsertChain(shared); err != nil {
|
||||
|
|
@ -1814,9 +1840,11 @@ func TestBlockchainRecovery(t *testing.T) {
|
|||
// Reopen broken blockchain again
|
||||
ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil, nil)
|
||||
defer ancient.Stop()
|
||||
|
||||
if num := ancient.CurrentBlock().Number.Uint64(); num != 0 {
|
||||
t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
|
||||
}
|
||||
|
||||
if num := ancient.CurrentSnapBlock().Number.Uint64(); 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 {
|
||||
t.Fatal("processing side chain failed:", err)
|
||||
}
|
||||
|
||||
t.Log("sidechain head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash())
|
||||
sidechainReceipts := make([]types.Receipts, len(sideblocks))
|
||||
for i, block := range sideblocks {
|
||||
|
|
@ -1846,6 +1875,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
|
|||
if _, err := tmpChain.InsertChain(canonblocks); err != nil {
|
||||
t.Fatal("processing canon chain failed:", err)
|
||||
}
|
||||
|
||||
t.Log("canon head:", tmpChain.CurrentBlock().Number, tmpChain.CurrentBlock().Hash())
|
||||
canonReceipts := make([]types.Receipts, len(canonblocks))
|
||||
for i, block := range canonblocks {
|
||||
|
|
@ -1876,6 +1906,7 @@ func TestInsertReceiptChainRollback(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("expected error from InsertReceiptChain.")
|
||||
}
|
||||
|
||||
if ancientChain.CurrentSnapBlock().Number.Uint64() != 0 {
|
||||
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 {
|
||||
t.Fatalf("can't import canon chain receipts: %v", err)
|
||||
}
|
||||
|
||||
if ancientChain.CurrentSnapBlock().Number.Uint64() != canonblocks[len(canonblocks)-1].NumberU64() {
|
||||
t.Fatalf("failed to insert ancient recept chain after rollback")
|
||||
}
|
||||
|
|
@ -1922,6 +1954,7 @@ func TestLowDiffLongChain(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.stopWithoutSaving()
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
|
|
@ -1984,6 +2017,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
// 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
|
||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
|
|
@ -2133,6 +2168,7 @@ func testInsertKnownChainData(t *testing.T, typ string) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
var (
|
||||
|
|
@ -2304,6 +2340,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
var (
|
||||
|
|
@ -2316,7 +2353,9 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
|
|||
for _, block := range blocks {
|
||||
headers = append(headers, block.Header())
|
||||
}
|
||||
|
||||
i, err := chain.InsertHeaderChain(headers, 1)
|
||||
|
||||
if err != nil {
|
||||
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.OffsetTime(-9)
|
||||
})
|
||||
|
||||
var heavyChain []*types.Block
|
||||
heavyChain = append(heavyChain, longChain[:parentIndex+1]...)
|
||||
heavyChain = append(heavyChain, heavyChainExt...)
|
||||
|
|
@ -2451,6 +2491,7 @@ func getLongAndShortChains() (*BlockChain, []*types.Block, []*types.Block, *Gene
|
|||
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 chain, longChain, heavyChain, genesis, nil
|
||||
}
|
||||
|
||||
|
|
@ -2464,11 +2505,13 @@ func TestReorgToShorterRemovesCanonMapping(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(canonblocks); err != nil {
|
||||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||
}
|
||||
|
||||
canonNum := chain.CurrentBlock().Number.Uint64()
|
||||
canonHash := chain.CurrentBlock().Hash()
|
||||
_, err = chain.InsertChain(sideblocks)
|
||||
|
|
@ -2502,6 +2545,7 @@ func TestReorgToShorterRemovesCanonMappingHeaderChain(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
// Convert into headers
|
||||
|
|
@ -2553,6 +2597,7 @@ func TestTransactionIndices(t *testing.T) {
|
|||
}
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
)
|
||||
|
||||
_, 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)
|
||||
if err != nil {
|
||||
|
|
@ -2606,6 +2651,7 @@ func TestTransactionIndices(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
|
||||
|
||||
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))
|
||||
limit = []uint64{0, 64 /* drop stale */, 32 /* shorten history */, 64 /* extend history */, 0 /* restore all */}
|
||||
|
||||
for _, l := range limit {
|
||||
l := l
|
||||
chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
var tail uint64
|
||||
|
||||
if l != 0 {
|
||||
tail = uint64(128) - l + 1
|
||||
}
|
||||
|
||||
chain.indexBlocks(rawdb.ReadTxIndexTail(ancientDb), 128, make(chan struct{}))
|
||||
check(&tail, chain)
|
||||
chain.Stop()
|
||||
|
|
@ -2649,6 +2699,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
|
|||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
)
|
||||
|
||||
_, 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)
|
||||
if err != nil {
|
||||
|
|
@ -2703,6 +2754,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
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.StopTimer()
|
||||
|
||||
block := chain.GetBlockByHash(chain.CurrentBlock().Hash())
|
||||
|
||||
if got := block.Transactions().Len(); got != numTxs*numBlocks {
|
||||
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 {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
|
|
@ -2937,6 +2992,7 @@ func TestDeleteCreateRevert(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
|
|
@ -3047,6 +3103,7 @@ func TestDeleteRecreateSlots(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
|
|
@ -3124,6 +3181,7 @@ func TestDeleteRecreateAccount(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
|
|
@ -3295,6 +3353,7 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
var asHash = func(num int) common.Hash {
|
||||
|
|
@ -3426,6 +3485,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
statedb, _ := chain.State()
|
||||
|
|
@ -3508,6 +3568,7 @@ func TestEIP2718Transition(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
|
|
@ -3596,6 +3657,7 @@ func TestEIP1559Transition(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
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.
|
||||
// It expects the state is recovered and all relevant chain markers are set correctly.
|
||||
func TestSetCanonical(t *testing.T) {
|
||||
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
|
||||
t.Parallel()
|
||||
var (
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
|
|
@ -3688,6 +3749,9 @@ func TestSetCanonical(t *testing.T) {
|
|||
signer = types.LatestSigner(gspec.Config)
|
||||
engine = ethash.NewFaker()
|
||||
)
|
||||
|
||||
//log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
|
||||
|
||||
// Generate and import the canonical chain
|
||||
_, 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)
|
||||
|
|
@ -3696,10 +3760,12 @@ func TestSetCanonical(t *testing.T) {
|
|||
}
|
||||
gen.AddTx(tx)
|
||||
})
|
||||
|
||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if n, err := chain.InsertChain(canon); err != nil {
|
||||
|
|
@ -3714,12 +3780,14 @@ func TestSetCanonical(t *testing.T) {
|
|||
}
|
||||
gen.AddTx(tx)
|
||||
})
|
||||
|
||||
for _, block := range side {
|
||||
err := chain.InsertBlockWithoutSetHead(block)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to insert into chain: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, block := range side {
|
||||
got := chain.GetBlockByHash(block.Hash())
|
||||
if got == nil {
|
||||
|
|
@ -3732,12 +3800,15 @@ func TestSetCanonical(t *testing.T) {
|
|||
if chain.CurrentBlock().Hash() != head.Hash() {
|
||||
t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash())
|
||||
}
|
||||
|
||||
if chain.CurrentSnapBlock().Hash() != head.Hash() {
|
||||
t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash())
|
||||
}
|
||||
|
||||
if chain.CurrentHeader().Hash() != head.Hash() {
|
||||
t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash())
|
||||
}
|
||||
|
||||
if !chain.HasState(head.Root()) {
|
||||
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
|
||||
{10, 11},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
var (
|
||||
gspec = &Genesis{
|
||||
|
|
@ -3796,6 +3868,7 @@ func TestCanonicalHashMarker(t *testing.T) {
|
|||
}
|
||||
engine = ethash.NewFaker()
|
||||
)
|
||||
|
||||
_, forkA, _ := GenerateChainWithGenesis(gspec, engine, c.forkA, 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 {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
// Insert forkA and forkB, the canonical should on forkA still
|
||||
if n, err := chain.InsertChain(forkA); err != nil {
|
||||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||
}
|
||||
|
||||
if n, err := chain.InsertChain(forkB); err != nil {
|
||||
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() {
|
||||
t.Fatalf("Unexpected block hash, want %x, got %x", head.Hash(), chain.CurrentBlock().Hash())
|
||||
}
|
||||
|
||||
if chain.CurrentSnapBlock().Hash() != head.Hash() {
|
||||
t.Fatalf("Unexpected fast block hash, want %x, got %x", head.Hash(), chain.CurrentSnapBlock().Hash())
|
||||
}
|
||||
|
||||
if chain.CurrentHeader().Hash() != head.Hash() {
|
||||
t.Fatalf("Unexpected head header, want %x, got %x", head.Hash(), chain.CurrentHeader().Hash())
|
||||
}
|
||||
|
||||
if !chain.HasState(head.Root()) {
|
||||
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++ {
|
||||
block := forkB[i]
|
||||
hash := chain.GetCanonicalHash(block.NumberU64())
|
||||
|
||||
if hash != block.Hash() {
|
||||
t.Fatalf("Unexpected canonical hash %d", block.NumberU64())
|
||||
}
|
||||
}
|
||||
|
||||
if c.forkA > c.forkB {
|
||||
for i := uint64(c.forkB) + 1; i <= uint64(c.forkA); i++ {
|
||||
hash := chain.GetCanonicalHash(i)
|
||||
|
|
@ -3852,6 +3932,7 @@ func TestCanonicalHashMarker(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
chain.Stop()
|
||||
}
|
||||
}
|
||||
|
|
@ -3873,6 +3954,7 @@ func TestTxIndexer(t *testing.T) {
|
|||
engine = ethash.NewFaker()
|
||||
nonce = uint64(0)
|
||||
)
|
||||
|
||||
_, 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)
|
||||
gen.AddTx(tx)
|
||||
|
|
@ -3885,12 +3967,15 @@ func TestTxIndexer(t *testing.T) {
|
|||
if number == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
block := blocks[number-1]
|
||||
|
||||
for _, tx := range block.Transactions() {
|
||||
lookup := rawdb.ReadTxLookupEntry(db, tx.Hash())
|
||||
if exist && lookup == nil {
|
||||
t.Fatalf("missing %d %x", number, tx.Hash().Hex())
|
||||
}
|
||||
|
||||
if !exist && lookup != nil {
|
||||
t.Fatalf("unexpected %d %x", number, tx.Hash().Hex())
|
||||
}
|
||||
|
|
@ -3907,12 +3992,15 @@ func TestTxIndexer(t *testing.T) {
|
|||
if tail == nil {
|
||||
t.Fatal("Failed to write tx index tail")
|
||||
}
|
||||
|
||||
if *tail != expTail {
|
||||
t.Fatalf("Unexpected tx index tail, want %v, got %d", expTail, *tail)
|
||||
}
|
||||
|
||||
if *tail != 0 {
|
||||
verifyRange(db, 0, *tail-1, false)
|
||||
}
|
||||
|
||||
verifyRange(db, *tail, 128, true)
|
||||
}
|
||||
|
||||
|
|
@ -4035,6 +4123,7 @@ func TestTxIndexer(t *testing.T) {
|
|||
tailC: 65,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
frdir := t.TempDir()
|
||||
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
|
||||
|
|
@ -4177,6 +4266,7 @@ func TestTransientStorageReset(t *testing.T) {
|
|||
ExtraEips: []int{1153}, // Enable transient storage EIP
|
||||
}
|
||||
)
|
||||
|
||||
code := append([]byte{
|
||||
// TLoad value with location 1
|
||||
byte(vm.PUSH1), 0x1,
|
||||
|
|
@ -4251,8 +4341,10 @@ func TestTransientStorageReset(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Failed to load state %v", err)
|
||||
}
|
||||
|
||||
loc := common.BytesToHash([]byte{1})
|
||||
slot := state.GetState(destAddress, loc)
|
||||
|
||||
if slot != (common.Hash{}) {
|
||||
t.Fatalf("Unexpected dirty storage slot")
|
||||
}
|
||||
|
|
@ -4335,9 +4427,11 @@ func TestEIP3651(t *testing.T) {
|
|||
b.AddTx(tx)
|
||||
})
|
||||
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), nil, gspec, nil, engine, vm.Config{Tracer: logger.NewMarkdownLogger(&logger.Config{}, os.Stderr)}, nil, nil, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tester chain: %v", err)
|
||||
}
|
||||
|
||||
if n, err := chain.InsertChain(blocks); err != nil {
|
||||
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.
|
||||
innerGas := vm.GasQuickStep*2 + params.ColdSloadCostEIP2929*2
|
||||
expectedGas := params.TxGas + 5*vm.GasFastestStep + vm.GasQuickStep + 100 + innerGas // 100 because 0xaaaa is in access list
|
||||
|
||||
if block.GasUsed() != expectedGas {
|
||||
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.
|
||||
actual := state.GetBalance(block.Coinbase())
|
||||
expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
|
||||
|
||||
if actual.Cmp(expected) != 0 {
|
||||
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).
|
||||
actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
|
||||
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
|
||||
|
||||
if actual.Cmp(expected) != 0 {
|
||||
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,11 +99,14 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
|||
if b.gasPool == nil {
|
||||
b.SetCoinbase(common.Address{})
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
b.txs = append(b.txs, tx)
|
||||
b.receipts = append(b.receipts, receipt)
|
||||
}
|
||||
|
|
@ -226,6 +229,7 @@ func (b *BlockGen) AddWithdrawal(w *types.Withdrawal) uint64 {
|
|||
cpy := *w
|
||||
cpy.Index = b.nextWithdrawalIndex()
|
||||
b.withdrawals = append(b.withdrawals, &cpy)
|
||||
|
||||
return cpy.Index
|
||||
}
|
||||
|
||||
|
|
@ -234,10 +238,12 @@ func (b *BlockGen) nextWithdrawalIndex() uint64 {
|
|||
if len(b.withdrawals) != 0 {
|
||||
return b.withdrawals[len(b.withdrawals)-1].Index + 1
|
||||
}
|
||||
|
||||
for i := b.i - 1; i >= 0; i-- {
|
||||
if wd := b.chain[i].Withdrawals(); len(wd) != 0 {
|
||||
return wd[len(wd)-1].Index + 1
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
// Correctly set the index if no parent had withdrawals.
|
||||
if wd := b.parent.Withdrawals(); len(wd) != 0 {
|
||||
|
|
@ -245,6 +251,7 @@ func (b *BlockGen) nextWithdrawalIndex() uint64 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
@ -334,6 +341,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
|||
if err != nil {
|
||||
panic(fmt.Sprintf("state write error: %v", err))
|
||||
}
|
||||
|
||||
if err := statedb.Database().TrieDB().Commit(root, false); err != nil {
|
||||
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) {
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
_, err := genesis.Commit(db, trie.NewDatabase(db))
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
blocks, receipts := GenerateChain(genesis.Config, genesis.ToBlock(), engine, db, n, gen)
|
||||
|
||||
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) {
|
||||
db, blocks := makeBlockChainWithGenesis(genesis, n, engine, seed)
|
||||
headers := make([]*types.Header, len(blocks))
|
||||
|
||||
for i, block := range blocks {
|
||||
headers[i] = block.Header()
|
||||
}
|
||||
|
||||
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) {
|
||||
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
|
||||
})
|
||||
|
||||
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) {
|
||||
b.SetCoinbase(common.Address{0: byte(seed), 19: byte(i)})
|
||||
})
|
||||
|
||||
return db, blocks
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,18 +122,22 @@ func TestGenerateWithdrawalChain(t *testing.T) {
|
|||
withdrawalIndex uint64
|
||||
head = blockchain.CurrentBlock().Number.Uint64()
|
||||
)
|
||||
|
||||
for i := 0; i < int(head); i++ {
|
||||
block := blockchain.GetBlockByNumber(uint64(i))
|
||||
if block == nil {
|
||||
t.Fatalf("block %d not found", i)
|
||||
}
|
||||
|
||||
if len(block.Withdrawals()) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for j := 0; j < len(block.Withdrawals()); j++ {
|
||||
if block.Withdrawals()[j].Index != withdrawalIndex {
|
||||
t.Fatalf("withdrawal index %d does not equal expected index %d", block.Withdrawals()[j].Index, withdrawalIndex)
|
||||
}
|
||||
|
||||
withdrawalIndex += 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,10 +83,13 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
|||
if _, err := bc.InsertChain(blocks); err != nil {
|
||||
t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
|
||||
}
|
||||
|
||||
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
|
||||
t.Fatalf("failed to commit contra-fork head for expansion: %v", err)
|
||||
}
|
||||
|
||||
bc.Stop()
|
||||
|
||||
blocks, _ = GenerateChain(&proConf, conBc.GetBlockByHash(conBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
|
||||
if _, err := conBc.InsertChain(blocks); err == nil {
|
||||
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 {
|
||||
t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
|
||||
}
|
||||
|
||||
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
|
||||
t.Fatalf("failed to commit pro-fork head for expansion: %v", err)
|
||||
}
|
||||
|
||||
bc.Stop()
|
||||
|
||||
blocks, _ = GenerateChain(&conConf, proBc.GetBlockByHash(proBc.CurrentBlock().Hash()), ethash.NewFaker(), genDb, 1, func(i int, gen *BlockGen) {})
|
||||
if _, err := proBc.InsertChain(blocks); err == nil {
|
||||
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 {
|
||||
t.Fatalf("failed to import contra-fork chain for expansion: %v", err)
|
||||
}
|
||||
|
||||
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
|
||||
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) {})
|
||||
if _, err := conBc.InsertChain(blocks); err != nil {
|
||||
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()
|
||||
|
||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().Number.Uint64()))
|
||||
|
||||
for j := 0; j < len(blocks)/2; j++ {
|
||||
blocks[j], blocks[len(blocks)-1-j] = blocks[len(blocks)-1-j], blocks[j]
|
||||
}
|
||||
|
||||
if _, err := bc.InsertChain(blocks); err != nil {
|
||||
t.Fatalf("failed to import pro-fork chain for expansion: %v", err)
|
||||
}
|
||||
|
||||
if err := bc.stateCache.TrieDB().Commit(bc.CurrentHeader().Root, false); err != nil {
|
||||
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) {})
|
||||
if _, err := proBc.InsertChain(blocks); err != nil {
|
||||
t.Fatalf("pro-fork chain didn't accept contra-fork block post-fork: %v", err)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
reorg := false
|
||||
externNum, localNum := extern.Number.Uint64(), current.Number.Uint64()
|
||||
|
||||
if externNum < localNum {
|
||||
reorg = true
|
||||
} else if externNum == localNum {
|
||||
|
|
|
|||
|
|
@ -71,27 +71,37 @@ type Genesis struct {
|
|||
|
||||
func ReadGenesis(db ethdb.Database) (*Genesis, error) {
|
||||
var genesis Genesis
|
||||
|
||||
stored := rawdb.ReadCanonicalHash(db, 0)
|
||||
|
||||
if (stored == common.Hash{}) {
|
||||
return nil, fmt.Errorf("invalid genesis hash in database: %x", stored)
|
||||
}
|
||||
|
||||
blob := rawdb.ReadGenesisStateSpec(db, stored)
|
||||
|
||||
if blob == nil {
|
||||
return nil, fmt.Errorf("genesis state missing from db")
|
||||
}
|
||||
|
||||
if len(blob) != 0 {
|
||||
if err := genesis.Alloc.UnmarshalJSON(blob); err != nil {
|
||||
return nil, fmt.Errorf("could not unmarshal genesis state json: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
genesis.Config = rawdb.ReadChainConfig(db, stored)
|
||||
|
||||
if genesis.Config == nil {
|
||||
return nil, fmt.Errorf("genesis config missing from db")
|
||||
}
|
||||
|
||||
genesisBlock := rawdb.ReadBlock(db, stored, 0)
|
||||
|
||||
if genesisBlock == nil {
|
||||
return nil, fmt.Errorf("genesis block missing from db")
|
||||
}
|
||||
|
||||
genesisHeader := genesisBlock.Header()
|
||||
genesis.Nonce = genesisHeader.Nonce.Uint64()
|
||||
genesis.Timestamp = genesisHeader.Time
|
||||
|
|
@ -136,6 +146,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
|||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
return statedb.Commit(false)
|
||||
}
|
||||
|
||||
|
|
@ -147,14 +158,17 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for addr, account := range *ga {
|
||||
statedb.AddBalance(addr, account.Balance)
|
||||
statedb.SetCode(addr, account.Code)
|
||||
statedb.SetNonce(addr, account.Nonce)
|
||||
|
||||
for key, value := range account.Storage {
|
||||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
|
||||
root, err := statedb.Commit(false)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -170,6 +184,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rawdb.WriteGenesisStateSpec(db, blockhash, blob)
|
||||
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.
|
||||
func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
|
||||
var alloc GenesisAlloc
|
||||
|
||||
blob := rawdb.ReadGenesisStateSpec(db, blockhash)
|
||||
if len(blob) != 0 {
|
||||
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 alloc.flush(db, triedb, blockhash)
|
||||
}
|
||||
|
||||
|
|
@ -295,6 +312,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
|||
if genesis != nil && genesis.Config == nil {
|
||||
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
|
||||
}
|
||||
|
||||
applyOverrides := func(config *params.ChainConfig) {
|
||||
if config != nil {
|
||||
// TODO marcello double check
|
||||
|
|
@ -312,10 +330,12 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
|||
} else {
|
||||
log.Info("Writing custom genesis block")
|
||||
}
|
||||
|
||||
block, err := genesis.Commit(db, triedb)
|
||||
if err != nil {
|
||||
return genesis.Config, common.Hash{}, err
|
||||
}
|
||||
|
||||
applyOverrides(genesis.Config)
|
||||
return genesis.Config, block.Hash(), nil
|
||||
}
|
||||
|
|
@ -331,10 +351,12 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
|||
if hash != stored {
|
||||
return genesis.Config, hash, &GenesisMismatchError{stored, hash}
|
||||
}
|
||||
|
||||
block, err := genesis.Commit(db, triedb)
|
||||
if err != nil {
|
||||
return genesis.Config, hash, err
|
||||
}
|
||||
|
||||
applyOverrides(genesis.Config)
|
||||
return genesis.Config, block.Hash(), nil
|
||||
}
|
||||
|
|
@ -357,6 +379,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
|||
rawdb.WriteChainConfig(db, stored, newcfg)
|
||||
return newcfg, stored, nil
|
||||
}
|
||||
|
||||
// nolint:errchkjson
|
||||
storedData, _ := json.Marshal(storedcfg)
|
||||
// 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`
|
||||
|
|
@ -373,7 +397,9 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
|
|||
if head == nil {
|
||||
return newcfg, stored, fmt.Errorf("missing head header")
|
||||
}
|
||||
|
||||
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)) {
|
||||
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 {
|
||||
return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()}
|
||||
}
|
||||
|
||||
return genesis.Config.Clique, nil
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
var withdrawals []*types.Withdrawal
|
||||
|
||||
if g.Config != nil && g.Config.IsShanghai(g.Timestamp) {
|
||||
head.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||
withdrawals = make([]*types.Withdrawal, 0)
|
||||
}
|
||||
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength {
|
||||
return nil, errors.New("can't start clique chain without signers")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ func TestInvalidCliqueConfig(t *testing.T) {
|
|||
block := DefaultGoerliGenesisBlock()
|
||||
block.ExtraData = []byte{}
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
|
||||
if _, err := block.Commit(db, trie.NewDatabase(db)); err == nil {
|
||||
t.Fatal("Expected error on invalid clique config")
|
||||
}
|
||||
|
|
@ -222,6 +223,8 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
|
|||
}
|
||||
hash, _ = alloc.deriveHash()
|
||||
)
|
||||
|
||||
// nolint : errchkjson
|
||||
blob, _ := json.Marshal(alloc)
|
||||
rawdb.WriteGenesisStateSpec(db, hash, blob)
|
||||
|
||||
|
|
|
|||
|
|
@ -400,6 +400,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time,
|
|||
if res.ignored > 0 {
|
||||
context = append(context, []interface{}{"ignored", res.ignored}...)
|
||||
}
|
||||
|
||||
log.Debug("Imported new block headers", context...)
|
||||
return res.status, err
|
||||
}
|
||||
|
|
@ -531,6 +532,7 @@ func (hc *HeaderChain) GetHeadersFrom(number, count uint64) []rlp.RawValue {
|
|||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
rlpData, _ := rlp.EncodeToBytes(header)
|
||||
headers = append(headers, rlpData)
|
||||
hash = header.ParentHash
|
||||
|
|
@ -607,12 +609,15 @@ func (hc *HeaderChain) setHead(headBlock uint64, headTime uint64, updateFn Updat
|
|||
batch = hc.chainDb.NewBatch()
|
||||
origin = true
|
||||
)
|
||||
|
||||
done := func(header *types.Header) bool {
|
||||
if headTime > 0 {
|
||||
return header.Time <= headTime
|
||||
}
|
||||
|
||||
return header.Number.Uint64() <= headBlock
|
||||
}
|
||||
|
||||
for hdr := hc.CurrentHeader(); hdr != nil && !done(hdr); hdr = hc.CurrentHeader() {
|
||||
num := hdr.Number.Uint64()
|
||||
|
||||
|
|
|
|||
|
|
@ -101,5 +101,6 @@ func (cacher *txSenderCacher) RecoverFromBlocks(signer types.Signer, blocks []*t
|
|||
for _, block := range blocks {
|
||||
txs = append(txs, block.Transactions()...)
|
||||
}
|
||||
|
||||
cacher.Recover(signer, txs)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c
|
|||
if err != nil {
|
||||
return // Also invalid block, bail out
|
||||
}
|
||||
|
||||
statedb.SetTxContext(tx.Hash(), i)
|
||||
if err := precacheTransaction(msg, p.config, gaspool, statedb, header, evm); err != nil {
|
||||
return // Ugh, something went horribly wrong, bail out
|
||||
|
|
|
|||
|
|
@ -82,10 +82,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||
default:
|
||||
}
|
||||
}
|
||||
|
||||
msg, err := TransactionToMessage(tx, types.MakeSigner(p.config, header.Number), header.BaseFee)
|
||||
if err != nil {
|
||||
return nil, nil, 0, fmt.Errorf("could not apply tx %d [%v]: %w", i, tx.Hash().Hex(), err)
|
||||
}
|
||||
|
||||
statedb.SetTxContext(tx.Hash(), i)
|
||||
receipt, err := applyTransaction(msg, p.config, gp, statedb, blockNumber, blockHash, tx, usedGas, vmenv, interruptCtx)
|
||||
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
|
||||
blockContext := NewEVMBlockContext(header, bc, author)
|
||||
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
|
||||
|
||||
return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv, interruptCtx)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||
}), signer, key1)
|
||||
return tx
|
||||
}
|
||||
|
||||
var mkDynamicCreationTx = func(nonce uint64, gasLimit uint64, gasTipCap, gasFeeCap *big.Int, data []byte) *types.Transaction {
|
||||
tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{
|
||||
Nonce: nonce,
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
|
|||
} else {
|
||||
gas = params.TxGas
|
||||
}
|
||||
|
||||
dataLen := uint64(len(data))
|
||||
// Bump the required gas by the amount of transactional data
|
||||
if dataLen > 0 {
|
||||
|
|
@ -108,6 +109,7 @@ func IntrinsicGas(data []byte, accessList types.AccessList, isContractCreation b
|
|||
if (math.MaxUint64-gas)/params.InitCodeWordGas < lenWords {
|
||||
return 0, ErrGasUintOverflow
|
||||
}
|
||||
|
||||
gas += lenWords * params.InitCodeWordGas
|
||||
}
|
||||
}
|
||||
|
|
@ -165,8 +167,10 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
|||
if baseFee != nil {
|
||||
msg.GasPrice = cmath.BigMin(msg.GasPrice.Add(msg.GasTipCap, baseFee), msg.GasFeeCap)
|
||||
}
|
||||
|
||||
var err error
|
||||
msg.From, err = types.Sender(s, tx)
|
||||
|
||||
return msg, err
|
||||
}
|
||||
|
||||
|
|
@ -239,6 +243,7 @@ func (st *StateTransition) to() common.Address {
|
|||
if st.msg == nil || st.msg.To == nil /* contract creation */ {
|
||||
return common.Address{}
|
||||
}
|
||||
|
||||
return *st.msg.To
|
||||
}
|
||||
|
||||
|
|
@ -246,17 +251,21 @@ func (st *StateTransition) buyGas() error {
|
|||
mgval := new(big.Int).SetUint64(st.msg.GasLimit)
|
||||
mgval = mgval.Mul(mgval, st.msg.GasPrice)
|
||||
balanceCheck := mgval
|
||||
|
||||
if st.msg.GasFeeCap != nil {
|
||||
balanceCheck = new(big.Int).SetUint64(st.msg.GasLimit)
|
||||
balanceCheck = balanceCheck.Mul(balanceCheck, st.msg.GasFeeCap)
|
||||
balanceCheck.Add(balanceCheck, st.msg.Value)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
if err := st.gp.SubGas(st.msg.GasLimit); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.gasRemaining += 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,
|
||||
msg.From.Hex(), l)
|
||||
}
|
||||
|
||||
if l := msg.GasTipCap.BitLen(); l > 256 {
|
||||
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas bit length: %d", ErrTipVeryHigh,
|
||||
msg.From.Hex(), l)
|
||||
}
|
||||
|
||||
if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 {
|
||||
return fmt.Errorf("%w: address %v, maxPriorityFeePerGas: %s, maxFeePerGas: %s", ErrTipAboveFeeCap,
|
||||
msg.From.Hex(), msg.GasTipCap, msg.GasFeeCap)
|
||||
|
|
@ -327,7 +338,9 @@ func (st *StateTransition) preCheck() error {
|
|||
// nil evm execution result.
|
||||
func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*ExecutionResult, error) {
|
||||
input1 := st.state.GetBalance(st.msg.From)
|
||||
|
||||
var input2 *big.Int
|
||||
|
||||
if !st.noFeeBurnAndTip {
|
||||
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 {
|
||||
tracer.CaptureTxStart(st.initialGas)
|
||||
|
||||
defer func() {
|
||||
tracer.CaptureTxEnd(st.gasRemaining)
|
||||
}()
|
||||
|
|
@ -365,9 +379,11 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if st.gasRemaining < gas {
|
||||
return nil, fmt.Errorf("%w: have %d, want %d", ErrIntrinsicGas, st.gasRemaining, gas)
|
||||
}
|
||||
|
||||
st.gasRemaining -= gas
|
||||
|
||||
// Check clause 6
|
||||
|
|
@ -406,7 +422,9 @@ func (st *StateTransition) TransitionDb(interruptCtx context.Context) (*Executio
|
|||
// After EIP-3529: refunds are capped to gasUsed / 5
|
||||
st.refundGas(params.RefundQuotientEIP3529)
|
||||
}
|
||||
|
||||
effectiveTip := msg.GasPrice
|
||||
|
||||
if rules.IsLondon {
|
||||
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 {
|
||||
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)
|
||||
|
||||
if !st.noFeeBurnAndTip {
|
||||
st.state.AddBalance(burntContractAddress, burnAmount)
|
||||
}
|
||||
}
|
||||
|
||||
if !st.noFeeBurnAndTip {
|
||||
st.state.AddBalance(st.evm.Context.Coinbase, amount)
|
||||
|
||||
output1 := new(big.Int).SetBytes(input1.Bytes())
|
||||
output2 := new(big.Int).SetBytes(input2.Bytes())
|
||||
|
||||
|
|
@ -472,6 +493,7 @@ func (st *StateTransition) refundGas(refundQuotient uint64) {
|
|||
if refund > st.state.GetRefund() {
|
||||
refund = st.state.GetRefund()
|
||||
}
|
||||
|
||||
st.gasRemaining += refund
|
||||
|
||||
// Return ETH for remaining gas, exchanged at the original rate.
|
||||
|
|
|
|||
|
|
@ -1984,10 +1984,12 @@ func TestIssue23496(t *testing.T) {
|
|||
SnapshotWait: true,
|
||||
}
|
||||
)
|
||||
|
||||
chain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
}
|
||||
|
||||
_, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, 4, func(i int, b *core.BlockGen) {
|
||||
b.SetCoinbase(common.Address{0x02})
|
||||
b.SetDifficulty(big.NewInt(1000000))
|
||||
|
|
@ -1997,14 +1999,17 @@ func TestIssue23496(t *testing.T) {
|
|||
if _, err := chain.InsertChain(blocks[:1]); err != nil {
|
||||
t.Fatalf("Failed to import canonical chain start: %v", err)
|
||||
}
|
||||
|
||||
err = chain.StateCache().TrieDB().Commit(blocks[0].Root(), true)
|
||||
if err != nil {
|
||||
t.Fatal("on trieDB.Commit", err)
|
||||
}
|
||||
|
||||
// Insert block B2 and commit the snapshot into disk
|
||||
if _, err := chain.InsertChain(blocks[1:2]); err != nil {
|
||||
t.Fatalf("Failed to import canonical chain start: %v", err)
|
||||
}
|
||||
|
||||
if err := chain.Snaps().Cap(blocks[1].Root(), 0); err != nil {
|
||||
t.Fatalf("Failed to flatten snapshots: %v", err)
|
||||
}
|
||||
|
|
@ -2035,20 +2040,24 @@ func TestIssue23496(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Failed to reopen persistent database: %v", err)
|
||||
}
|
||||
|
||||
defer db.Close()
|
||||
|
||||
chain, err = core.NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to recreate chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
|
||||
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
|
||||
}
|
||||
|
||||
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != 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) {
|
||||
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 {
|
||||
t.Fatalf("Failed to import canonical chain tail: %v", err)
|
||||
}
|
||||
|
||||
if head := chain.CurrentHeader(); head.Number.Uint64() != uint64(4) {
|
||||
t.Errorf("Head header mismatch: have %d, want %d", head.Number, 4)
|
||||
}
|
||||
|
||||
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != 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) {
|
||||
t.Errorf("Head block mismatch: have %d, want %d", head.Number, uint64(4))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1984,10 +1984,12 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
|
|||
config.SnapshotLimit = 256
|
||||
config.SnapshotWait = true
|
||||
}
|
||||
|
||||
chain, err := core.NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
}
|
||||
|
||||
defer chain.Stop()
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
canonblocks, _ := core.GenerateChain(gspec.Config, gspec.ToBlock(), engine, rawdb.NewMemoryDatabase(), tt.canonicalBlocks, func(i int, b *core.BlockGen) {
|
||||
b.SetCoinbase(common.Address{0x02})
|
||||
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 {
|
||||
t.Errorf("Head header mismatch: have %d, want %d", head.Number, tt.expHeadHeader)
|
||||
}
|
||||
|
||||
if head := chain.CurrentSnapBlock(); head.Number.Uint64() != 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 {
|
||||
t.Errorf("Head block mismatch: have %d, want %d", head.Number, tt.expHeadBlock)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,10 +84,12 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*core.BlockChain, []*type
|
|||
// will happen during the block insertion.
|
||||
cacheConfig = core.DefaultCacheConfig
|
||||
)
|
||||
|
||||
chain, err := core.NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create chain: %v", err)
|
||||
}
|
||||
|
||||
genDb, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, basic.chainBlocks, func(i int, b *core.BlockGen) {})
|
||||
|
||||
// Insert the blocks with configured settings.
|
||||
|
|
@ -326,6 +328,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
|
|||
TrieTimeLimit: 5 * time.Minute,
|
||||
SnapshotLimit: 0,
|
||||
}
|
||||
|
||||
newchain, err := core.NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to recreate chain: %v", err)
|
||||
|
|
@ -401,6 +404,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
|||
if err != nil {
|
||||
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) {})
|
||||
newchain.InsertChain(newBlocks)
|
||||
newchain.Stop()
|
||||
|
|
@ -422,6 +426,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Failed to recreate chain: %v", err)
|
||||
}
|
||||
|
||||
defer newchain.Stop()
|
||||
snaptest.verify(t, newchain, blocks)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4705,15 +4705,18 @@ func BenchmarkMultiAccountBatchInsert(b *testing.B) {
|
|||
defer pool.Stop()
|
||||
b.ReportAllocs()
|
||||
batches := make(types.Transactions, b.N)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
key, _ := crypto.GenerateKey()
|
||||
account := crypto.PubkeyToAddress(key.PublicKey)
|
||||
pool.currentState.AddBalance(account, big.NewInt(1000000))
|
||||
|
||||
tx := transaction(uint64(0), 100000, key)
|
||||
batches[i] = tx
|
||||
}
|
||||
// Benchmark importing the transactions into the queue
|
||||
b.ResetTimer()
|
||||
|
||||
for _, tx := range batches {
|
||||
pool.AddRemotesSync([]*types.Transaction{tx})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -508,6 +508,7 @@ func TestEip2929Cases(t *testing.T) {
|
|||
ops := strings.Join(instrs, ", ")
|
||||
fmt.Printf("### Case %d\n\n", id)
|
||||
id++
|
||||
|
||||
fmt.Printf("%v\n\nBytecode: \n```\n%#x\n```\nOperations: \n```\n%v\n```\n\n",
|
||||
comment,
|
||||
code, ops)
|
||||
|
|
|
|||
10
eth/api.go
10
eth/api.go
|
|
@ -267,6 +267,7 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
|
|||
_, stateDb := api.eth.miner.Pending()
|
||||
return stateDb.RawDump(opts), nil
|
||||
}
|
||||
|
||||
var header *types.Header
|
||||
if blockNr == rpc.LatestBlockNumber {
|
||||
header = api.eth.blockchain.CurrentBlock()
|
||||
|
|
@ -281,9 +282,11 @@ func (api *DebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error) {
|
|||
}
|
||||
header = block.Header()
|
||||
}
|
||||
|
||||
if header == nil {
|
||||
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
|
||||
}
|
||||
|
||||
stateDb, err := api.eth.BlockChain().StateAt(header.Root)
|
||||
if err != nil {
|
||||
return state.Dump{}, err
|
||||
|
|
@ -419,10 +422,13 @@ func (api *DebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash,
|
|||
if block == nil {
|
||||
return StorageRangeResult{}, fmt.Errorf("block %#x not found", blockHash)
|
||||
}
|
||||
|
||||
_, _, statedb, release, err := api.eth.stateAtTransaction(ctx, block, txIndex, 0)
|
||||
|
||||
if err != nil {
|
||||
return StorageRangeResult{}, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
st, err := statedb.StorageTrie(contractAddress)
|
||||
|
|
@ -523,6 +529,7 @@ func (api *DebugAPI) getModifiedAccounts(startBlock, endBlock *types.Block) ([]c
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newTrie, err := trie.NewStateTrie(trie.StateTrieID(endBlock.Root()), triedb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -599,6 +606,7 @@ func (api *DebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error
|
|||
return uint64(i), nil
|
||||
}
|
||||
}
|
||||
|
||||
return 0, errors.New("no state found")
|
||||
}
|
||||
|
||||
|
|
@ -609,6 +617,8 @@ func (api *DebugAPI) SetTrieFlushInterval(interval string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
api.eth.blockchain.SetTrieFlushInterval(t)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,24 +74,32 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
|
|||
if number == rpc.LatestBlockNumber {
|
||||
return b.eth.blockchain.CurrentBlock(), nil
|
||||
}
|
||||
|
||||
if number == rpc.FinalizedBlockNumber {
|
||||
if !b.eth.Merger().TDDReached() {
|
||||
return nil, errors.New("'finalized' tag not supported on pre-merge network")
|
||||
}
|
||||
|
||||
block := b.eth.blockchain.CurrentFinalBlock()
|
||||
|
||||
if block != nil {
|
||||
return block, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("finalized block not found")
|
||||
}
|
||||
|
||||
if number == rpc.SafeBlockNumber {
|
||||
if !b.eth.Merger().TDDReached() {
|
||||
return nil, errors.New("'safe' tag not supported on pre-merge network")
|
||||
}
|
||||
|
||||
block := b.eth.blockchain.CurrentSafeBlock()
|
||||
|
||||
if block != nil {
|
||||
return block, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("safe block not found")
|
||||
}
|
||||
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()
|
||||
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
|
||||
}
|
||||
|
||||
if number == rpc.FinalizedBlockNumber {
|
||||
if !b.eth.Merger().TDDReached() {
|
||||
return nil, errors.New("'finalized' tag not supported on pre-merge network")
|
||||
}
|
||||
|
||||
header := b.eth.blockchain.CurrentFinalBlock()
|
||||
|
||||
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
|
||||
}
|
||||
|
||||
if number == rpc.SafeBlockNumber {
|
||||
if !b.eth.Merger().TDDReached() {
|
||||
return nil, errors.New("'safe' tag not supported on pre-merge network")
|
||||
}
|
||||
|
||||
header := b.eth.blockchain.CurrentSafeBlock()
|
||||
|
||||
return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), 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{}) {
|
||||
return nil, errors.New("invalid arguments; expect hash and no special block numbers")
|
||||
}
|
||||
|
||||
if body := b.eth.blockchain.GetBody(hash); body != nil {
|
||||
return body, nil
|
||||
}
|
||||
|
||||
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)
|
||||
context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
|
||||
|
||||
return vm.NewEVM(context, txContext, state, b.eth.blockchain.Config(), *vmConfig), state.Error, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ func TestStorageRangeAt(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
result, err := storageRangeAt(tr, test.start, test.limit)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil {
|
||||
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.NotifyFull = config.Miner.NotifyFull
|
||||
cliqueConfig, err := core.LoadCliqueConfig(chainDb, config.Genesis)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -180,6 +182,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
if gpoParams.Default == nil {
|
||||
gpoParams.Default = config.Miner.GasPrice
|
||||
}
|
||||
|
||||
ethereum.APIBackend.gpo = gasprice.NewOracle(ethereum.APIBackend, gpoParams)
|
||||
|
||||
// Override the chain config with provided settings.
|
||||
|
|
@ -199,6 +202,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
// END: Bor changes
|
||||
|
||||
bcVersion := rawdb.ReadDatabaseVersion(chainDb)
|
||||
|
||||
var dbVer = "<nil>"
|
||||
if bcVersion != nil {
|
||||
dbVer = fmt.Sprintf("%d", *bcVersion)
|
||||
|
|
@ -259,6 +263,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
if config.TxPool.Journal != "" {
|
||||
config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal)
|
||||
}
|
||||
|
||||
ethereum.txPool = txpool.NewTxPool(config.TxPool, ethereum.blockchain.Config(), ethereum.blockchain)
|
||||
|
||||
// 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 {
|
||||
checkpoint = params.TrustedCheckpoints[ethereum.blockchain.Genesis().Hash()]
|
||||
}
|
||||
|
||||
if ethereum.handler, err = newHandler(&handlerConfig{
|
||||
Database: chainDb,
|
||||
Chain: ethereum.blockchain,
|
||||
|
|
@ -294,6 +300,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ethereum.snapDialCandidates, err = dnsclient.NewIterator(ethereum.config.SnapDiscoveryURLs...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI {
|
|||
if eth.BlockChain().Config().TerminalTotalDifficulty == nil {
|
||||
log.Warn("Engine API started but chain not configured for merge yet")
|
||||
}
|
||||
|
||||
api := &ConsensusAPI{
|
||||
eth: eth,
|
||||
remoteBlocks: newHeaderQueue(),
|
||||
|
|
@ -143,6 +144,7 @@ func NewConsensusAPI(eth *eth.Ethereum) *ConsensusAPI {
|
|||
invalidTipsets: make(map[common.Hash]*types.Header),
|
||||
}
|
||||
eth.Downloader().SetBadBlockCallback(api.setInvalidAncestor)
|
||||
|
||||
go api.heartbeat()
|
||||
|
||||
return api
|
||||
|
|
@ -167,10 +169,12 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa
|
|||
if payloadAttributes.Withdrawals != nil {
|
||||
return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1"))
|
||||
}
|
||||
|
||||
if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp) {
|
||||
return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("forkChoiceUpdateV1 called post-shanghai"))
|
||||
}
|
||||
}
|
||||
|
||||
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 api.forkchoiceUpdated(update, payloadAttributes)
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +201,7 @@ func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes)
|
|||
return errors.New("missing withdrawals list")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -242,7 +248,9 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
|||
merger.ReachTTD()
|
||||
api.eth.Downloader().Cancel()
|
||||
}
|
||||
|
||||
context := []interface{}{"number", header.Number, "hash", header.Hash()}
|
||||
|
||||
if update.FinalizedBlockHash != (common.Hash{}) {
|
||||
if finalized == nil {
|
||||
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}...)
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("Forkchoice requested sync to new head", context...)
|
||||
|
||||
if err := api.eth.Downloader().BeaconSync(api.eth.SyncMode(), header, finalized); err != nil {
|
||||
return engine.STATUS_SYNCING, err
|
||||
}
|
||||
|
||||
return engine.STATUS_SYNCING, nil
|
||||
}
|
||||
// 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)
|
||||
return engine.STATUS_INVALID, errors.New("TDs unavailable for TDD check")
|
||||
}
|
||||
|
||||
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)))
|
||||
return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
|
||||
}
|
||||
|
||||
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)))
|
||||
return engine.ForkChoiceResponse{PayloadStatus: engine.INVALID_TERMINAL_BLOCK, PayloadID: nil}, nil
|
||||
}
|
||||
}
|
||||
|
||||
valid := func(id *engine.PayloadID) engine.ForkChoiceResponse {
|
||||
return engine.ForkChoiceResponse{
|
||||
PayloadStatus: engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &update.HeadBlockHash},
|
||||
|
|
@ -349,16 +363,20 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
|||
if api.localBlocks.has(id) {
|
||||
return valid(&id), nil
|
||||
}
|
||||
|
||||
payload, err := api.eth.Miner().BuildPayload(args)
|
||||
if err != nil {
|
||||
log.Error("Failed to build payload", "err", err)
|
||||
return valid(nil), engine.InvalidPayloadAttributes.With(err)
|
||||
}
|
||||
|
||||
api.localBlocks.put(id, payload)
|
||||
|
||||
return valid(&id), nil
|
||||
}
|
||||
|
||||
return valid(nil), nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExchangeTransitionConfigurationV1 checks the given configuration against
|
||||
// the configuration of the node.
|
||||
|
|
@ -387,6 +405,7 @@ func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.Transit
|
|||
}
|
||||
return nil, fmt.Errorf("invalid terminal block hash")
|
||||
}
|
||||
|
||||
return &engine.TransitionConfigurationV1{TerminalTotalDifficulty: (*hexutil.Big)(ttd)}, nil
|
||||
}
|
||||
|
||||
|
|
@ -396,6 +415,7 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.Execu
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data.ExecutionPayload, nil
|
||||
}
|
||||
|
||||
|
|
@ -418,6 +438,7 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl
|
|||
if params.Withdrawals != nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1"))
|
||||
}
|
||||
|
||||
return api.newPayload(params)
|
||||
}
|
||||
|
||||
|
|
@ -430,6 +451,7 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
|
|||
} else if params.Withdrawals != nil {
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("non-nil withdrawals pre-shanghai"))
|
||||
}
|
||||
|
||||
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 {
|
||||
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()
|
||||
|
||||
return engine.PayloadStatusV1{Status: engine.VALID, LatestValidHash: &hash}, nil
|
||||
}
|
||||
// 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
|
||||
gptd = api.eth.BlockChain().GetTd(parent.ParentHash(), parent.NumberU64()-1)
|
||||
)
|
||||
|
||||
if ptd.Cmp(ttd) < 0 {
|
||||
log.Warn("Ignoring pre-merge payload", "number", params.Number, "hash", params.BlockHash, "td", ptd, "ttd", ttd)
|
||||
return engine.INVALID_TERMINAL_BLOCK, nil
|
||||
}
|
||||
|
||||
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)
|
||||
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) {
|
||||
api.remoteBlocks.put(block.Hash(), block.Header())
|
||||
log.Warn("State not available, ignoring new payload")
|
||||
|
||||
return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil
|
||||
}
|
||||
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()
|
||||
}
|
||||
hash := block.Hash()
|
||||
|
||||
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.
|
||||
log.Warn("Ignoring payload while snap syncing", "number", block.NumberU64(), "hash", block.Hash())
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
// Not too many failures yet, mark the head of the invalid chain as invalid
|
||||
if check != head {
|
||||
log.Warn("Marked new chain head as invalid", "hash", head, "badnumber", invalid.Number, "badhash", badHash)
|
||||
|
||||
for len(api.invalidTipsets) >= invalidTipsetsCap {
|
||||
for key := range api.invalidTipsets {
|
||||
delete(api.invalidTipsets, key)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
api.invalidTipsets[head] = invalid
|
||||
}
|
||||
// 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 {
|
||||
lastValid = &common.Hash{}
|
||||
}
|
||||
|
||||
failure := "links to previously rejected block"
|
||||
|
||||
return &engine.PayloadStatusV1{
|
||||
Status: engine.INVALID,
|
||||
LatestValidHash: lastValid,
|
||||
|
|
@ -648,6 +681,7 @@ func (api *ConsensusAPI) invalid(err error, latestValid *types.Header) engine.Pa
|
|||
}
|
||||
}
|
||||
errorMsg := err.Error()
|
||||
|
||||
return engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: ¤tHash, ValidationError: &errorMsg}
|
||||
}
|
||||
|
||||
|
|
@ -702,8 +736,10 @@ func (api *ConsensusAPI) heartbeat() {
|
|||
} else {
|
||||
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()
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
@ -718,10 +754,12 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
|
|||
// of block bodies by the engine api.
|
||||
func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engine.ExecutionPayloadBodyV1 {
|
||||
var bodies = make([]*engine.ExecutionPayloadBodyV1, len(hashes))
|
||||
|
||||
for i, hash := range hashes {
|
||||
block := api.eth.BlockChain().GetBlockByHash(hash)
|
||||
bodies[i] = getBody(block)
|
||||
}
|
||||
|
||||
return bodies
|
||||
}
|
||||
|
||||
|
|
@ -731,20 +769,25 @@ func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64)
|
|||
if start == 0 || count == 0 {
|
||||
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
|
||||
}
|
||||
|
||||
if count > 1024 {
|
||||
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count))
|
||||
}
|
||||
// limit count up until current
|
||||
current := api.eth.BlockChain().CurrentBlock().Number.Uint64()
|
||||
last := uint64(start) + uint64(count) - 1
|
||||
|
||||
if last > current {
|
||||
last = current
|
||||
}
|
||||
|
||||
bodies := make([]*engine.ExecutionPayloadBodyV1, 0, uint64(count))
|
||||
|
||||
for i := uint64(start); i <= last; i++ {
|
||||
block := api.eth.BlockChain().GetBlockByNumber(i)
|
||||
bodies = append(bodies, getBody(block))
|
||||
}
|
||||
|
||||
return bodies, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ var (
|
|||
func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
||||
config := *params.AllEthashProtocolChanges
|
||||
engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker()))
|
||||
|
||||
if merged {
|
||||
config.TerminalTotalDifficulty = common.Big0
|
||||
config.TerminalTotalDifficultyPassed = true
|
||||
|
|
@ -78,6 +79,7 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
|||
generate := func(i int, g *core.BlockGen) {
|
||||
g.OffsetTime(5)
|
||||
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)
|
||||
g.AddTx(tx)
|
||||
testNonce++
|
||||
|
|
@ -89,6 +91,7 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
|
|||
for _, b := range blocks {
|
||||
totalDifficulty.Add(totalDifficulty, b.Difficulty())
|
||||
}
|
||||
|
||||
config.TerminalTotalDifficulty = totalDifficulty
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +112,7 @@ func TestEth2AssembleBlock(t *testing.T) {
|
|||
t.Fatalf("error signing transaction, err=%v", err)
|
||||
}
|
||||
ethservice.TxPool().AddLocal(tx)
|
||||
|
||||
blockParams := engine.PayloadAttributes{
|
||||
Timestamp: blocks[9].Time() + 5,
|
||||
}
|
||||
|
|
@ -127,12 +131,15 @@ func assembleWithTransactions(api *ConsensusAPI, parentHash common.Hash, params
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if have, want := len(execData.Transactions), want; have != want {
|
||||
err = fmt.Errorf("invalid number of transactions, have %d want %d", have, want)
|
||||
continue
|
||||
}
|
||||
|
||||
return execData, nil
|
||||
}
|
||||
|
||||
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
|
||||
api.eth.TxPool().AddRemotesSync(blocks[9].Transactions())
|
||||
|
||||
blockParams := engine.PayloadAttributes{
|
||||
Timestamp: blocks[8].Time() + 5,
|
||||
}
|
||||
|
|
@ -180,12 +188,14 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
|
|||
// We need to properly set the terminal total difficulty
|
||||
genesis.Config.TerminalTotalDifficulty.Sub(genesis.Config.TerminalTotalDifficulty, blocks[9].Difficulty())
|
||||
n, ethservice := startEthService(t, genesis, blocks[:9])
|
||||
|
||||
defer n.Close()
|
||||
|
||||
api := NewConsensusAPI(ethservice)
|
||||
|
||||
// Put the 10th block's tx in the pool and produce a new block
|
||||
ethservice.TxPool().AddLocals(blocks[9].Transactions())
|
||||
|
||||
blockParams := engine.PayloadAttributes{
|
||||
Timestamp: blocks[8].Time() + 5,
|
||||
}
|
||||
|
|
@ -195,11 +205,13 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
|
|||
FinalizedBlockHash: common.Hash{},
|
||||
}
|
||||
_, err := api.ForkchoiceUpdatedV1(fcState, &blockParams)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
// give the payload some time to be built
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
payloadID := (&miner.BuildPayloadArgs{
|
||||
Parent: fcState.HeadBlockHash,
|
||||
Timestamp: blockParams.Timestamp,
|
||||
|
|
@ -207,17 +219,21 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
|
|||
Random: blockParams.Random,
|
||||
}).Id()
|
||||
execData, err := api.GetPayloadV1(payloadID)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error getting payload, err=%v", err)
|
||||
}
|
||||
|
||||
if len(execData.Transactions) != blocks[9].Transactions().Len() {
|
||||
t.Fatalf("invalid number of transactions %d != 1", len(execData.Transactions))
|
||||
}
|
||||
// Test invalid payloadID
|
||||
var invPayload engine.PayloadID
|
||||
|
||||
copy(invPayload[:], payloadID[:])
|
||||
invPayload[0] = ^invPayload[0]
|
||||
_, err = api.GetPayloadV1(invPayload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatal("expected error retrieving invalid payload")
|
||||
}
|
||||
|
|
@ -287,6 +303,7 @@ func TestInvalidPayloadTimestamp(t *testing.T) {
|
|||
|
||||
func TestEth2NewBlock(t *testing.T) {
|
||||
t.Skip("ETH2 in Bor")
|
||||
|
||||
genesis, preMergeBlocks := generateMergeChain(10, false)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
defer n.Close()
|
||||
|
|
@ -316,11 +333,13 @@ func TestEth2NewBlock(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("Failed to create the executable data %v", err)
|
||||
}
|
||||
|
||||
block, err := engine.ExecutableDataToBlock(*execData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to convert executable data to block %v", err)
|
||||
}
|
||||
newResp, err := api.NewPayloadV1(*execData)
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
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")
|
||||
}
|
||||
checkLogEvents(t, newLogCh, rmLogsCh, 0, 0)
|
||||
|
||||
fcState := engine.ForkchoiceStateV1{
|
||||
HeadBlockHash: block.Hash(),
|
||||
SafeBlockHash: block.Hash(),
|
||||
FinalizedBlockHash: block.Hash(),
|
||||
}
|
||||
|
||||
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
|
||||
t.Fatalf("Failed to insert block: %v", err)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -350,22 +372,28 @@ func TestEth2NewBlock(t *testing.T) {
|
|||
var (
|
||||
head = ethservice.BlockChain().CurrentBlock().Number.Uint64()
|
||||
)
|
||||
|
||||
parent = preMergeBlocks[len(preMergeBlocks)-1]
|
||||
for i := 0; i < 10; i++ {
|
||||
execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{
|
||||
Timestamp: parent.Time() + 6,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create the executable data %v", err)
|
||||
}
|
||||
|
||||
block, err := engine.ExecutableDataToBlock(*execData)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to convert executable data to block %v", err)
|
||||
}
|
||||
|
||||
newResp, err := api.NewPayloadV1(*execData)
|
||||
if err != nil || newResp.Status != "VALID" {
|
||||
t.Fatalf("Failed to insert block: %v", err)
|
||||
}
|
||||
|
||||
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != head {
|
||||
t.Fatalf("Chain head shouldn't be updated")
|
||||
}
|
||||
|
|
@ -375,9 +403,11 @@ func TestEth2NewBlock(t *testing.T) {
|
|||
SafeBlockHash: block.Hash(),
|
||||
FinalizedBlockHash: block.Hash(),
|
||||
}
|
||||
|
||||
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
|
||||
t.Fatalf("Failed to insert block: %v", err)
|
||||
}
|
||||
|
||||
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64() {
|
||||
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 {
|
||||
api := NewConsensusAPI(ethservice)
|
||||
var blocks []*types.Header
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
callback(parent)
|
||||
|
||||
var w []*types.Withdrawal
|
||||
|
||||
if withdrawals != nil {
|
||||
w = withdrawals[i]
|
||||
}
|
||||
|
||||
payload := getNewPayload(t, api, parent, w)
|
||||
execResp, err := api.NewPayloadV2(*payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("can't execute payload: %v", err)
|
||||
}
|
||||
|
||||
if execResp.Status != engine.VALID {
|
||||
t.Fatalf("invalid status: %v", execResp.Status)
|
||||
}
|
||||
|
||||
fcState := engine.ForkchoiceStateV1{
|
||||
HeadBlockHash: payload.BlockHash,
|
||||
SafeBlockHash: payload.ParentHash,
|
||||
FinalizedBlockHash: payload.ParentHash,
|
||||
}
|
||||
|
||||
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
|
||||
t.Fatalf("Failed to insert block: %v", err)
|
||||
}
|
||||
|
||||
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number {
|
||||
t.Fatal("Chain head should be updated")
|
||||
}
|
||||
|
||||
if ethservice.BlockChain().CurrentFinalBlock().Number.Uint64() != payload.Number-1 {
|
||||
t.Fatal("Finalized block should be updated")
|
||||
}
|
||||
parent = ethservice.BlockChain().CurrentBlock()
|
||||
blocks = append(blocks, parent)
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
|
|
@ -588,6 +628,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
|
|||
|
||||
genesis, preMergeBlocks := generateMergeChain(10, false)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
|
||||
defer n.Close()
|
||||
|
||||
var (
|
||||
|
|
@ -597,6 +638,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
|
|||
// This EVM code generates a log when the contract is created.
|
||||
logCode = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
|
||||
)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
statedb, _ := ethservice.BlockChain().StateAt(parent.Root)
|
||||
tx := types.MustSignNewTx(testKey, signer, &types.LegacyTx{
|
||||
|
|
@ -607,6 +649,7 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
|
|||
Data: logCode,
|
||||
})
|
||||
ethservice.TxPool().AddRemotesSync([]*types.Transaction{tx})
|
||||
|
||||
var (
|
||||
params = engine.PayloadAttributes{
|
||||
Timestamp: parent.Time + 1,
|
||||
|
|
@ -622,45 +665,59 @@ func TestNewPayloadOnInvalidChain(t *testing.T) {
|
|||
resp engine.ForkChoiceResponse
|
||||
err error
|
||||
)
|
||||
|
||||
for i := 0; ; i++ {
|
||||
if resp, err = api.ForkchoiceUpdatedV1(fcState, ¶ms); err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
||||
if resp.PayloadStatus.Status != engine.VALID {
|
||||
t.Fatalf("error preparing payload, invalid status: %v", resp.PayloadStatus.Status)
|
||||
}
|
||||
|
||||
// give the payload some time to be built
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
if payload, err = api.GetPayloadV1(*resp.PayloadID); err != nil {
|
||||
t.Fatalf("can't get payload: %v", err)
|
||||
}
|
||||
|
||||
if len(payload.Transactions) > 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// No luck this time we need to update the params and try again.
|
||||
params.Timestamp = params.Timestamp + 1
|
||||
|
||||
if i > 10 {
|
||||
t.Fatalf("payload should not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
execResp, err := api.NewPayloadV1(*payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("can't execute payload: %v", err)
|
||||
}
|
||||
|
||||
if execResp.Status != engine.VALID {
|
||||
t.Fatalf("invalid status: %v", execResp.Status)
|
||||
}
|
||||
|
||||
fcState = engine.ForkchoiceStateV1{
|
||||
HeadBlockHash: payload.BlockHash,
|
||||
SafeBlockHash: payload.ParentHash,
|
||||
FinalizedBlockHash: payload.ParentHash,
|
||||
}
|
||||
|
||||
if _, err := api.ForkchoiceUpdatedV1(fcState, nil); err != nil {
|
||||
t.Fatalf("Failed to insert block: %v", err)
|
||||
}
|
||||
|
||||
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != payload.Number {
|
||||
t.Fatalf("Chain head should be updated")
|
||||
}
|
||||
|
||||
parent = ethservice.BlockChain().CurrentBlock()
|
||||
}
|
||||
}
|
||||
|
|
@ -674,9 +731,11 @@ func assembleBlock(api *ConsensusAPI, parentHash common.Hash, params *engine.Pay
|
|||
Withdrawals: params.Withdrawals,
|
||||
}
|
||||
payload, err := api.eth.Miner().BuildPayload(args)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return payload.ResolveFull().ExecutionPayload, nil
|
||||
}
|
||||
|
||||
|
|
@ -685,6 +744,7 @@ func TestEmptyBlocks(t *testing.T) {
|
|||
|
||||
genesis, preMergeBlocks := generateMergeChain(10, false)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
|
||||
defer n.Close()
|
||||
|
||||
commonAncestor := ethservice.BlockChain().CurrentBlock()
|
||||
|
|
@ -700,9 +760,11 @@ func TestEmptyBlocks(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if status.Status != engine.VALID {
|
||||
t.Errorf("invalid status: expected VALID got: %v", status.Status)
|
||||
}
|
||||
|
||||
if !bytes.Equal(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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if status.Status != engine.INVALID {
|
||||
t.Errorf("invalid status: expected INVALID got: %v", status.Status)
|
||||
}
|
||||
|
|
@ -734,9 +797,11 @@ func TestEmptyBlocks(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if status.Status != engine.SYNCING {
|
||||
t.Errorf("invalid status: expected SYNCING got: %v", status.Status)
|
||||
}
|
||||
|
||||
if status.LatestValidHash != nil {
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
|
|
@ -765,6 +831,7 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData {
|
|||
txs, _ := decodeTransactions(data.Transactions)
|
||||
number := big.NewInt(0)
|
||||
number.SetUint64(data.Number)
|
||||
|
||||
header := &types.Header{
|
||||
ParentHash: data.ParentHash,
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
|
|
@ -784,18 +851,22 @@ func setBlockhash(data *engine.ExecutableData) *engine.ExecutableData {
|
|||
}
|
||||
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
|
||||
data.BlockHash = block.Hash()
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||
var txs = make([]*types.Transaction, len(enc))
|
||||
|
||||
for i, encTx := range enc {
|
||||
var tx types.Transaction
|
||||
if err := tx.UnmarshalBinary(encTx); err != nil {
|
||||
return nil, fmt.Errorf("invalid transaction %d: %v", i, err)
|
||||
}
|
||||
|
||||
txs[i] = &tx
|
||||
}
|
||||
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
|
|
@ -806,13 +877,16 @@ func TestTrickRemoteBlockCache(t *testing.T) {
|
|||
genesis, preMergeBlocks := generateMergeChain(10, false)
|
||||
nodeA, ethserviceA := startEthService(t, genesis, preMergeBlocks)
|
||||
nodeB, ethserviceB := startEthService(t, genesis, preMergeBlocks)
|
||||
|
||||
defer nodeA.Close()
|
||||
defer nodeB.Close()
|
||||
|
||||
for nodeB.Server().NodeInfo().Ports.Listener == 0 {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
nodeA.Server().AddPeer(nodeB.Server().Self())
|
||||
nodeB.Server().AddPeer(nodeA.Server().Self())
|
||||
|
||||
apiA := NewConsensusAPI(ethserviceA)
|
||||
apiB := NewConsensusAPI(ethserviceB)
|
||||
|
||||
|
|
@ -850,6 +924,7 @@ func TestTrickRemoteBlockCache(t *testing.T) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if status.Status == engine.VALID {
|
||||
t.Error("invalid status: VALID on an invalid chain")
|
||||
}
|
||||
|
|
@ -858,9 +933,11 @@ func TestTrickRemoteBlockCache(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if resp.PayloadStatus.Status == engine.VALID {
|
||||
t.Error("invalid status: VALID on an invalid chain")
|
||||
}
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
|
@ -871,6 +948,7 @@ func TestInvalidBloom(t *testing.T) {
|
|||
genesis, preMergeBlocks := generateMergeChain(10, false)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
ethservice.Merger().ReachTTD()
|
||||
|
||||
defer n.Close()
|
||||
|
||||
commonAncestor := ethservice.BlockChain().CurrentBlock()
|
||||
|
|
@ -883,9 +961,11 @@ func TestInvalidBloom(t *testing.T) {
|
|||
payload := getNewPayload(t, api, commonAncestor, nil)
|
||||
payload.LogsBloom = append(payload.LogsBloom, byte(1))
|
||||
status, err := api.NewPayloadV1(*payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if status.Status != engine.INVALID {
|
||||
t.Errorf("invalid status: expected INVALID got: %v", status.Status)
|
||||
}
|
||||
|
|
@ -896,7 +976,9 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
|
|||
|
||||
genesis, preMergeBlocks := generateMergeChain(100, false)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
|
||||
defer n.Close()
|
||||
|
||||
api := NewConsensusAPI(ethservice)
|
||||
|
||||
// Test parent already post TTD in FCU
|
||||
|
|
@ -907,9 +989,11 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
|
|||
FinalizedBlockHash: common.Hash{},
|
||||
}
|
||||
resp, err := api.ForkchoiceUpdatedV1(fcState, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error sending forkchoice, err=%v", err)
|
||||
}
|
||||
|
||||
if resp.PayloadStatus != engine.INVALID_TERMINAL_BLOCK {
|
||||
t.Fatalf("error sending invalid forkchoice, invalid status: %v", resp.PayloadStatus.Status)
|
||||
}
|
||||
|
|
@ -922,9 +1006,11 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
|
|||
FeeRecipient: parent.Coinbase(),
|
||||
}
|
||||
payload, err := api.eth.Miner().BuildPayload(args)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
||||
data := *payload.Resolve().ExecutionPayload
|
||||
// We need to recompute the blockhash, since the miner computes a wrong (correct) blockhash
|
||||
txs, _ := decodeTransactions(data.Transactions)
|
||||
|
|
@ -952,6 +1038,7 @@ func TestNewPayloadOnInvalidTerminalBlock(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("error sending NewPayload, err=%v", err)
|
||||
}
|
||||
|
||||
if resp2 != engine.INVALID_TERMINAL_BLOCK {
|
||||
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)
|
||||
n, ethservice := startEthService(t, genesis, preMergeBlocks)
|
||||
|
||||
defer n.Close()
|
||||
|
||||
var (
|
||||
api = NewConsensusAPI(ethservice)
|
||||
parent = preMergeBlocks[len(preMergeBlocks)-1]
|
||||
)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
execData, err := assembleBlock(api, parent.Hash(), &engine.PayloadAttributes{
|
||||
Timestamp: parent.Time() + 5,
|
||||
|
|
@ -1005,13 +1094,17 @@ func TestSimultaneousNewBlock(t *testing.T) {
|
|||
t.Fatal(testErr)
|
||||
}
|
||||
}
|
||||
|
||||
block, err := engine.ExecutableDataToBlock(*execData)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to convert executable data to block %v", err)
|
||||
}
|
||||
|
||||
if ethservice.BlockChain().CurrentBlock().Number.Uint64() != block.NumberU64()-1 {
|
||||
t.Fatalf("Chain head shouldn't be updated")
|
||||
}
|
||||
|
||||
fcState := engine.ForkchoiceStateV1{
|
||||
HeadBlockHash: block.Hash(),
|
||||
SafeBlockHash: block.Hash(),
|
||||
|
|
@ -1040,9 +1133,11 @@ func TestSimultaneousNewBlock(t *testing.T) {
|
|||
t.Fatal(testErr)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
parent = block
|
||||
}
|
||||
}
|
||||
|
|
@ -1059,6 +1154,7 @@ func TestWithdrawals(t *testing.T) {
|
|||
|
||||
n, ethservice := startEthService(t, genesis, blocks)
|
||||
ethservice.Merger().ReachTTD()
|
||||
|
||||
defer n.Close()
|
||||
|
||||
api := NewConsensusAPI(ethservice)
|
||||
|
|
@ -1073,9 +1169,11 @@ func TestWithdrawals(t *testing.T) {
|
|||
HeadBlockHash: parent.Hash(),
|
||||
}
|
||||
resp, err := api.ForkchoiceUpdatedV2(fcState, &blockParams)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
||||
if 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,
|
||||
}).Id()
|
||||
execData, err := api.GetPayloadV2(payloadID)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error getting payload, err=%v", err)
|
||||
}
|
||||
|
||||
if execData.ExecutionPayload.StateRoot != parent.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
|
||||
_, err = api.ForkchoiceUpdatedV2(fcState, &blockParams)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
|
@ -1136,9 +1237,11 @@ func TestWithdrawals(t *testing.T) {
|
|||
Withdrawals: blockParams.Withdrawals,
|
||||
}).Id()
|
||||
execData, err = api.GetPayloadV2(payloadID)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error getting payload, err=%v", err)
|
||||
}
|
||||
|
||||
if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil {
|
||||
t.Fatalf("error validating payload: %v", err)
|
||||
} else if status.Status != engine.VALID {
|
||||
|
|
@ -1148,6 +1251,7 @@ func TestWithdrawals(t *testing.T) {
|
|||
// 11: set block as head.
|
||||
fcState.HeadBlockHash = execData.ExecutionPayload.BlockHash
|
||||
_, err = api.ForkchoiceUpdatedV2(fcState, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
|
@ -1157,6 +1261,7 @@ func TestWithdrawals(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("unable to load db: %v", err)
|
||||
}
|
||||
|
||||
for i, w := range blockParams.Withdrawals {
|
||||
// w.Amount is in gwei, balance in wei
|
||||
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)
|
||||
ethservice.Merger().ReachTTD()
|
||||
|
||||
defer n.Close()
|
||||
|
||||
api := NewConsensusAPI(ethservice)
|
||||
|
|
@ -1185,6 +1291,7 @@ func TestNilWithdrawals(t *testing.T) {
|
|||
blockParams engine.PayloadAttributes
|
||||
wantErr bool
|
||||
}
|
||||
|
||||
tests := []test{
|
||||
// Before Shanghai
|
||||
{
|
||||
|
|
@ -1254,8 +1361,10 @@ func TestNilWithdrawals(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Fatal("wanted error on fcuv2 with invalid withdrawals")
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error preparing payload, err=%v", err)
|
||||
}
|
||||
|
|
@ -1268,9 +1377,11 @@ func TestNilWithdrawals(t *testing.T) {
|
|||
Random: test.blockParams.Random,
|
||||
}).Id()
|
||||
execData, err := api.GetPayloadV2(payloadID)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("error getting payload, err=%v", err)
|
||||
}
|
||||
|
||||
if status, err := api.NewPayloadV2(*execData.ExecutionPayload); err != nil {
|
||||
t.Fatalf("error validating payload: %v", err)
|
||||
} 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[0] = nil // should be filtered out by miner
|
||||
withdrawals[1] = make([]*types.Withdrawal, 0)
|
||||
|
||||
for i := 2; i < len(withdrawals); i++ {
|
||||
addr := make([]byte, 20)
|
||||
|
||||
crand.Read(addr)
|
||||
|
||||
withdrawals[i] = []*types.Withdrawal{
|
||||
{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)
|
||||
postShanghaiBlocks := make([]*types.Block, len(postShanghaiHeaders))
|
||||
|
||||
for i, header := range postShanghaiHeaders {
|
||||
postShanghaiBlocks[i] = ethservice.BlockChain().GetBlock(header.Hash(), header.Number.Uint64())
|
||||
}
|
||||
|
||||
return n, ethservice, append(blocks, postShanghaiBlocks...)
|
||||
}
|
||||
|
||||
|
|
@ -1325,6 +1441,7 @@ func allHashes(blocks []*types.Block) []common.Hash {
|
|||
for _, b := range blocks {
|
||||
hashes = append(hashes, b.Hash())
|
||||
}
|
||||
|
||||
return hashes
|
||||
}
|
||||
func allBodies(blocks []*types.Block) []*types.Body {
|
||||
|
|
@ -1332,6 +1449,7 @@ func allBodies(blocks []*types.Block) []*types.Body {
|
|||
for _, b := range blocks {
|
||||
bodies = append(bodies, b.Body())
|
||||
}
|
||||
|
||||
return bodies
|
||||
}
|
||||
|
||||
|
|
@ -1340,6 +1458,7 @@ func TestGetBlockBodiesByHash(t *testing.T) {
|
|||
|
||||
node, eth, blocks := setupBodies(t)
|
||||
api := NewConsensusAPI(eth)
|
||||
|
||||
defer node.Close()
|
||||
|
||||
tests := []struct {
|
||||
|
|
@ -1398,6 +1517,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
|
|||
|
||||
node, eth, blocks := setupBodies(t)
|
||||
api := NewConsensusAPI(eth)
|
||||
|
||||
defer node.Close()
|
||||
|
||||
tests := []struct {
|
||||
|
|
@ -1464,6 +1584,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(result) == len(test.results) {
|
||||
for i, r := range result {
|
||||
if !equalBody(test.results[i], r) {
|
||||
|
|
@ -1481,7 +1602,9 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
|
|||
|
||||
node, eth, _ := setupBodies(t)
|
||||
api := NewConsensusAPI(eth)
|
||||
|
||||
defer node.Close()
|
||||
|
||||
tests := []struct {
|
||||
start hexutil.Uint64
|
||||
count hexutil.Uint64
|
||||
|
|
@ -1512,11 +1635,13 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
|
|||
want: engine.TooLargeRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tests {
|
||||
result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count)
|
||||
if err == nil {
|
||||
t.Fatalf("test %d: expected error, got %v", i, result)
|
||||
}
|
||||
|
||||
if have, want := err.Error(), tc.want.Error(); 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 {
|
||||
return false
|
||||
}
|
||||
|
||||
if len(a.Transactions) != len(b.TransactionData) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, tx := range a.Transactions {
|
||||
data, _ := tx.MarshalBinary()
|
||||
if !bytes.Equal(data, b.TransactionData[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(a.Withdrawals, b.Withdrawals)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,10 +97,12 @@ func (q *payloadQueue) has(id engine.PayloadID) bool {
|
|||
if item == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if item.id == id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,12 +47,14 @@ func RegisterFullSyncTester(stack *node.Node, backend *eth.Ethereum, block *type
|
|||
closed: make(chan struct{}),
|
||||
}
|
||||
stack.RegisterLifecycle(cl)
|
||||
|
||||
return cl, nil
|
||||
}
|
||||
|
||||
// Start launches the beacon sync with provided sync target.
|
||||
func (tester *FullSyncTester) Start() error {
|
||||
tester.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer tester.wg.Done()
|
||||
|
||||
|
|
@ -85,6 +87,7 @@ func (tester *FullSyncTester) Start() error {
|
|||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -93,5 +96,6 @@ func (tester *FullSyncTester) Start() error {
|
|||
func (tester *FullSyncTester) Stop() error {
|
||||
close(tester.closed)
|
||||
tester.wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -271,6 +271,7 @@ func (d *Downloader) findBeaconAncestor() (uint64, error) {
|
|||
// until sync errors or is finished.
|
||||
func (d *Downloader) fetchBeaconHeaders(from uint64) error {
|
||||
var head *types.Header
|
||||
|
||||
_, tail, _, err := d.skeleton.Bounds()
|
||||
if err != nil {
|
||||
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
|
||||
// blocks in the network.
|
||||
var localHeaders []*types.Header
|
||||
|
||||
if from < tail.Number.Uint64() {
|
||||
count := tail.Number.Uint64() - from
|
||||
if count > uint64(fsMinFullBlocks) {
|
||||
return fmt.Errorf("invalid origin (%d) of beacon sync (%d)", from, tail.Number)
|
||||
}
|
||||
|
||||
localHeaders = d.readHeaderRange(tail, int(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)
|
||||
|
||||
log.Warn("Pivot seemingly stale, moving", "old", d.pivotHeader.Number, "new", number)
|
||||
|
||||
if d.pivotHeader = d.skeleton.Header(number); d.pivotHeader == nil {
|
||||
if number < tail.Number.Uint64() {
|
||||
dist := tail.Number.Uint64() - number
|
||||
|
|
@ -320,6 +324,7 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
|
|||
if d.pivotHeader == nil {
|
||||
log.Error("Pivot header is not found", "number", number)
|
||||
d.pivotLock.Unlock()
|
||||
|
||||
return errNoPivotHeader
|
||||
}
|
||||
// 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 {
|
||||
return fmt.Errorf("missing beacon header %d", from)
|
||||
}
|
||||
|
||||
headers = append(headers, header)
|
||||
hashes = append(hashes, headers[i].Hash())
|
||||
from++
|
||||
|
|
|
|||
|
|
@ -371,6 +371,7 @@ func (d *Downloader) LegacySync(id string, head common.Hash, td, ttd *big.Int, m
|
|||
if errors.Is(err, ErrMergeTransition) {
|
||||
return err // This is an expected fault, don't keep printing it in a spin-loop
|
||||
}
|
||||
|
||||
log.Warn("Synchronisation failed, retrying", "err", err)
|
||||
return err
|
||||
}
|
||||
|
|
@ -568,6 +569,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td, ttd *
|
|||
rawdb.WriteLastPivotNumber(d.stateDB, pivotNumber)
|
||||
}
|
||||
}
|
||||
|
||||
d.committed.Store(true)
|
||||
if mode == SnapSync && pivot.Number.Uint64() != 0 {
|
||||
d.committed.Store(false)
|
||||
|
|
@ -1677,6 +1679,7 @@ func (d *Downloader) processSnapSyncContent() error {
|
|||
if d.chainInsertHook != nil {
|
||||
d.chainInsertHook(results)
|
||||
}
|
||||
|
||||
d.reportSnapSyncProgress(false)
|
||||
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
|
||||
d.committed.Store(true)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1859,17 +1863,22 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea
|
|||
current = last
|
||||
headers []*types.Header
|
||||
)
|
||||
|
||||
for {
|
||||
parent := d.lightchain.GetHeaderByHash(current.ParentHash)
|
||||
if parent == nil {
|
||||
break // The chain is not continuous, or the chain is exhausted
|
||||
}
|
||||
|
||||
headers = append(headers, parent)
|
||||
|
||||
if len(headers) >= count {
|
||||
break
|
||||
}
|
||||
|
||||
current = parent
|
||||
}
|
||||
|
||||
return headers
|
||||
}
|
||||
|
||||
|
|
@ -1889,15 +1898,20 @@ func (d *Downloader) reportSnapSyncProgress(force bool) {
|
|||
bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable)
|
||||
receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable)
|
||||
)
|
||||
|
||||
syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes)
|
||||
|
||||
if syncedBytes == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
header = d.blockchain.CurrentHeader()
|
||||
block = d.blockchain.CurrentSnapBlock()
|
||||
)
|
||||
|
||||
syncedBlocks := block.Number.Uint64() - d.syncStartBlock
|
||||
|
||||
if syncedBlocks == 0 {
|
||||
return
|
||||
}
|
||||
|
|
@ -1907,12 +1921,14 @@ func (d *Downloader) reportSnapSyncProgress(force bool) {
|
|||
// We're going to cheat for non-merged networks, but that's fine
|
||||
latest = d.pivotHeader
|
||||
}
|
||||
|
||||
if latest == nil {
|
||||
// This should really never happen, but add some defensive code for now.
|
||||
// TODO(karalabe): Remove it eventually if we don't see it blow.
|
||||
log.Error("Nil latest block in sync progress report")
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
left = latest.Number.Uint64() - block.Number.Uint64()
|
||||
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())
|
||||
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))
|
||||
|
||||
d.syncLogTime = time.Now()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,9 +69,11 @@ func newTesterWithNotification(t *testing.T, success func()) *downloadTester {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
t.Cleanup(func() {
|
||||
db.Close()
|
||||
})
|
||||
|
||||
gspec := &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
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 {
|
||||
t.Fatalf("synchronised headers mismatch: have %v, want %v", hs, headers)
|
||||
}
|
||||
|
||||
if bs := int(tester.chain.CurrentBlock().Number.Uint64()) + 1; bs != blocks {
|
||||
t.Fatalf("synchronised blocks mismatch: have %v, want %v", bs, blocks)
|
||||
}
|
||||
|
||||
if rs := int(tester.chain.CurrentSnapBlock().Number.Uint64()) + 1; 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
|
||||
var blocked atomic.Uint32
|
||||
|
||||
proceed := make(chan struct{})
|
||||
tester.downloader.chainInsertHook = func(results []*fetchResult) {
|
||||
blocked.Store(uint32(len(results)))
|
||||
|
|
@ -984,9 +989,11 @@ func testEmptyShortCircuit(t *testing.T, protocol uint, mode SyncMode) {
|
|||
receiptsNeeded++
|
||||
}
|
||||
}
|
||||
|
||||
if int(bodiesHave.Load()) != bodiesNeeded {
|
||||
t.Errorf("body retrieval count mismatch: have %v, want %v", bodiesHave.Load(), bodiesNeeded)
|
||||
}
|
||||
|
||||
if int(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 full local chain", local: blockCacheMaxItems - 15 - 1},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ func (d *Downloader) concurrentFetch(queue typedQueue, beaconMode bool) error {
|
|||
_, exp := timeouts.Peek()
|
||||
timeout.Reset(time.Until(time.Unix(0, -exp)))
|
||||
}
|
||||
|
||||
delete(ordering, req)
|
||||
|
||||
// New timeout potentially set if there are more requests pending,
|
||||
|
|
|
|||
|
|
@ -436,6 +436,7 @@ func (q *queue) ReserveHeaders(p *peerConnection, count int) *fetchRequest {
|
|||
continue
|
||||
}
|
||||
}
|
||||
|
||||
send = from
|
||||
}
|
||||
// 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 {
|
||||
return errInvalidBody
|
||||
}
|
||||
|
||||
if header.WithdrawalsHash == nil {
|
||||
// nil hash means that withdrawals should not be present in body
|
||||
if withdrawalLists[index] != nil {
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ func XTestDelivery(t *testing.T) {
|
|||
uncleHashes[i] = types.CalcUncleHash(uncles)
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
_, err := q.DeliverBodies(peer.id, txset, txsHashes, uncleset, uncleHashes, nil, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("delivered %d bodies %v\n", len(txset), err)
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ func (s *skeleton) sync(head *types.Header) (*types.Header, error) {
|
|||
if linked {
|
||||
s.filler.resume()
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if filled := s.filler.suspend(); filled != nil {
|
||||
// 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, s.progress.Subchains[i+1].Next)
|
||||
}
|
||||
|
||||
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,
|
||||
// just the metadata. We could implement a cleanup mechanism,
|
||||
// but further modifying corrupted state is kind of asking
|
||||
// for it. Unless there's a good enough reason to risk it,
|
||||
// better to live with the small database junk.
|
||||
|
||||
s.progress.Subchains = s.progress.Subchains[:1]
|
||||
}
|
||||
}
|
||||
break
|
||||
|
|
@ -1116,6 +1119,7 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
|
|||
end = number // delete until the requested threshold
|
||||
batch = s.db.NewBatch()
|
||||
)
|
||||
|
||||
s.progress.Subchains[0].Tail = number
|
||||
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
|
||||
s.saveSyncStatus(batch)
|
||||
|
||||
for n := start; n < end; n++ {
|
||||
// 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
|
||||
|
|
@ -1148,17 +1153,21 @@ func (s *skeleton) cleanStales(filled *types.Header) error {
|
|||
if err := batch.Write(); err != nil {
|
||||
log.Crit("Failed to write beacon trim data", "err", err)
|
||||
}
|
||||
|
||||
batch.Reset()
|
||||
|
||||
s.progress.Subchains[0].Tail = tmpTail
|
||||
s.progress.Subchains[0].Next = tmpNext
|
||||
s.saveSyncStatus(batch)
|
||||
}
|
||||
|
||||
rawdb.DeleteSkeletonHeader(batch, n)
|
||||
}
|
||||
|
||||
if err := batch.Write(); err != nil {
|
||||
log.Crit("Failed to write beacon trim data", "err", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -1187,19 +1196,23 @@ func (s *skeleton) Bounds() (head *types.Header, tail *types.Header, final *type
|
|||
return nil, nil, nil, err
|
||||
}
|
||||
head = rawdb.ReadSkeletonHeader(s.db, progress.Subchains[0].Head)
|
||||
|
||||
if head == nil {
|
||||
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)
|
||||
|
||||
if tail == nil {
|
||||
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() {
|
||||
final = rawdb.ReadSkeletonHeader(s.db, *progress.Finalized)
|
||||
if final == nil {
|
||||
return nil, nil, nil, fmt.Errorf("finalized skeleton header %d is missing", *progress.Finalized)
|
||||
}
|
||||
}
|
||||
|
||||
return head, tail, final, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ func (hf *hookedBackfiller) suspend() *types.Header {
|
|||
if hf.suspendHook != nil {
|
||||
return hf.suspendHook()
|
||||
}
|
||||
|
||||
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)))
|
||||
|
||||
hashes := make([]common.Hash, len(headers))
|
||||
|
|
@ -487,6 +489,7 @@ func TestSkeletonSyncExtend(t *testing.T) {
|
|||
skeleton.Sync(tt.head, nil, true)
|
||||
|
||||
<-wait
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
@ -530,6 +533,7 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
|
|||
for i := 0; i < len(chain)/2; i++ { // Fork at block #5000
|
||||
sidechain = append(sidechain, chain[i])
|
||||
}
|
||||
|
||||
for i := len(chain) / 2; i < len(chain); i++ {
|
||||
sidechain = append(sidechain, &types.Header{
|
||||
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
|
||||
filler := newHookedBackfiller()
|
||||
|
||||
if tt.fill {
|
||||
var filled *types.Header
|
||||
|
||||
|
|
@ -892,18 +897,23 @@ func TestSkeletonSyncRetrievals(t *testing.T) {
|
|||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !tt.unpredictable {
|
||||
var served uint64
|
||||
for _, peer := range tt.peers {
|
||||
served += peer.served.Load()
|
||||
}
|
||||
|
||||
if served != tt.midserve {
|
||||
t.Errorf("test %d, mid state: served headers mismatch: have %d, want %d", i, served, tt.midserve)
|
||||
}
|
||||
|
||||
var drops uint64
|
||||
|
||||
for _, peer := range tt.peers {
|
||||
drops += peer.dropped.Load()
|
||||
}
|
||||
|
||||
if 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
|
||||
}
|
||||
waitStart = time.Now()
|
||||
|
||||
for waitTime := 20 * time.Millisecond; time.Since(waitStart) < 2*time.Second; waitTime = waitTime * 2 {
|
||||
time.Sleep(waitTime)
|
||||
// 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 {
|
||||
served += peer.served.Load()
|
||||
}
|
||||
|
||||
if tt.newPeer != nil {
|
||||
served += tt.newPeer.served.Load()
|
||||
}
|
||||
|
||||
if served != tt.endserve {
|
||||
t.Errorf("test %d, end state: served headers mismatch: have %d, want %d", i, served, tt.endserve)
|
||||
}
|
||||
|
||||
drops := uint64(0)
|
||||
|
||||
for _, peer := range tt.peers {
|
||||
drops += peer.dropped.Load()
|
||||
}
|
||||
|
||||
if tt.newPeer != nil {
|
||||
drops += tt.newPeer.dropped.Load()
|
||||
}
|
||||
|
||||
if drops != tt.enddrop {
|
||||
t.Errorf("test %d, end state: dropped peers mismatch: have %d, want %d", i, drops, tt.middrop)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,7 +163,10 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
|||
// time. But we don't have any recent state for full sync.
|
||||
// In these cases however it's safe to reenable snap sync.
|
||||
fullBlock, snapBlock := h.chain.CurrentBlock(), h.chain.CurrentSnapBlock()
|
||||
|
||||
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
|
||||
// preventive we won't allow it to roll over to snap sync until
|
||||
// we have it working
|
||||
|
|
@ -171,8 +174,6 @@ func newHandler(config *handlerConfig) (*handler, error) {
|
|||
// TODO(snap): Uncomment when we have snap sync working
|
||||
// h.snapSync = uint32(1)
|
||||
// log.Warn("Switch sync mode from full sync to snap sync")
|
||||
|
||||
log.Warn("Preventing switching sync mode from full sync to snap sync")
|
||||
}
|
||||
} else {
|
||||
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()
|
||||
td = h.chain.GetTd(hash, number)
|
||||
)
|
||||
|
||||
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 {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
go func(number uint64, hash common.Hash, req *eth.Request) {
|
||||
// Ensure the request gets cancelled in case of error/drop
|
||||
defer req.Close()
|
||||
|
|
|
|||
|
|
@ -697,6 +697,7 @@ func testBroadcastBlock(t *testing.T, peers, bcasts int) {
|
|||
}
|
||||
// Initiate a block propagation across the peers
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
header := source.chain.CurrentBlock()
|
||||
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.UncleHash[0]++
|
||||
|
||||
malformedTransactions := head
|
||||
malformedTransactions.TxHash[0]++
|
||||
|
||||
malformedEverything := head
|
||||
malformedEverything.UncleHash[0]++
|
||||
malformedEverything.TxHash[0]++
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ func handleMessage(backend Backend, peer *Peer) error {
|
|||
if peer.Version() == ETH67 {
|
||||
handlers = eth67
|
||||
}
|
||||
|
||||
if peer.Version() >= ETH68 {
|
||||
handlers = eth68
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,9 +111,11 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
|
|||
if _, err := chain.InsertChain(bs); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, block := range bs {
|
||||
chain.StateCache().TrieDB().Commit(block.Root(), false)
|
||||
}
|
||||
|
||||
txconfig := txpool.DefaultConfig
|
||||
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)
|
||||
if tt.available[j] && len(bodies) < tt.expected {
|
||||
block := backend.chain.GetBlockByHash(hash)
|
||||
|
||||
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,
|
||||
})
|
||||
msg, err := peer.app.ReadMsg()
|
||||
|
||||
if !drop {
|
||||
if err != nil {
|
||||
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.
|
||||
accounts := []common.Address{testAddr, acc1Addr, acc2Addr}
|
||||
|
||||
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
|
||||
root := backend.chain.GetBlockByNumber(i).Root()
|
||||
reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil)
|
||||
|
|
@ -640,6 +645,7 @@ func testGetBlockReceipts(t *testing.T, protocol uint) {
|
|||
hashes []common.Hash
|
||||
receipts [][]*types.Receipt
|
||||
)
|
||||
|
||||
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
|
||||
block := backend.chain.GetBlockByNumber(i)
|
||||
|
||||
|
|
|
|||
|
|
@ -387,10 +387,12 @@ func handleBlockBodies66(backend Backend, msg Decoder, peer *Peer) error {
|
|||
for i, body := range res.BlockBodiesPacket {
|
||||
txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher)
|
||||
uncleHashes[i] = types.CalcUncleHash(body.Uncles)
|
||||
|
||||
if body.Withdrawals != nil {
|
||||
withdrawalHashes[i] = types.DeriveSha(types.Withdrawals(body.Withdrawals), hasher)
|
||||
}
|
||||
}
|
||||
|
||||
return [][]common.Hash{txsHashes, uncleHashes, withdrawalHashes}
|
||||
}
|
||||
return peer.dispatchResponse(&Response{
|
||||
|
|
@ -440,6 +442,7 @@ func handleNewPooledTransactionHashes66(backend Backend, msg Decoder, peer *Peer
|
|||
if !backend.AcceptTxs() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ann := new(NewPooledTransactionHashesPacket66)
|
||||
if err := msg.Decode(ann); err != nil {
|
||||
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() {
|
||||
return nil
|
||||
}
|
||||
|
||||
ann := new(NewPooledTransactionHashesPacket68)
|
||||
|
||||
if err := msg.Decode(ann); err != nil {
|
||||
return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
|
@ -468,6 +474,7 @@ func handleNewPooledTransactionHashes68(backend Backend, msg Decoder, peer *Peer
|
|||
for _, hash := range ann.Hashes {
|
||||
peer.markTransaction(hash)
|
||||
}
|
||||
|
||||
return backend.Handle(peer, ann)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,6 +254,7 @@ func (p *BlockBodiesPacket) Unpack() ([][]*types.Transaction, [][]*types.Header,
|
|||
for i, body := range *p {
|
||||
txset[i], uncleset[i], withdrawalset[i] = body.Transactions, body.Uncles, body.Withdrawals
|
||||
}
|
||||
|
||||
return txset, uncleset, withdrawalset
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1510,6 +1510,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
|
|||
trie, _ := trie.New(id, db)
|
||||
storageTries[common.BytesToHash(key)] = trie
|
||||
}
|
||||
|
||||
return db.Scheme(), accTrie, entries, storageTries, storageEntries
|
||||
}
|
||||
|
||||
|
|
@ -1537,6 +1538,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
|
|||
stNodes *trie.NodeSet
|
||||
stEntries entrySlice
|
||||
)
|
||||
|
||||
if boundary {
|
||||
stRoot, stNodes, stEntries = makeBoundaryStorageTrie(common.BytesToHash(key), slots, db)
|
||||
} else {
|
||||
|
|
@ -1572,15 +1574,19 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for i := uint64(1); i <= uint64(accounts); i++ {
|
||||
key := key32(i)
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(key), storageRoots[common.BytesToHash(key)])
|
||||
|
||||
trie, err := trie.New(id, db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
storageTries[common.BytesToHash(key)] = trie
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
sort.Sort(entries)
|
||||
|
||||
root, nodes := trie.Commit(false)
|
||||
|
||||
return root, nodes, entries
|
||||
}
|
||||
|
||||
|
|
@ -1654,12 +1662,15 @@ func makeBoundaryStorageTrie(owner common.Hash, n int, db *trie.Database) (commo
|
|||
entries = append(entries, elem)
|
||||
}
|
||||
sort.Sort(entries)
|
||||
|
||||
root, nodes := trie.Commit(false)
|
||||
|
||||
return root, nodes, entries
|
||||
}
|
||||
|
||||
func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
triedb := trie.NewDatabase(rawdb.NewDatabase(db))
|
||||
accTrie, err := trie.New(trie.StateTrieID(root), triedb)
|
||||
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)
|
||||
}
|
||||
accounts++
|
||||
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root)
|
||||
storeTrie, err := trie.NewStateTrie(id, triedb)
|
||||
|
|
@ -1716,6 +1728,7 @@ func TestSyncAccountPerformance(t *testing.T) {
|
|||
})
|
||||
}
|
||||
)
|
||||
|
||||
nodeScheme, sourceAccountTrie, elems := makeAccountTrieNoStorage(100)
|
||||
|
||||
mkSource := func(name string) *testPeer {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe
|
|||
// function to deref it.
|
||||
if statedb, err = eth.blockchain.StateAt(block.Root()); err == nil {
|
||||
statedb.Database().TrieDB().Reference(block.Root(), common.Hash{})
|
||||
|
||||
return statedb, func() {
|
||||
statedb.Database().TrieDB().Dereference(block.Root())
|
||||
}, nil
|
||||
|
|
@ -188,6 +189,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe
|
|||
nodes, imgs := database.TrieDB().Size()
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
vmenv := vm.NewEVM(context, txContext, statedb, eth.blockchain.Config(), vm.Config{})
|
||||
statedb.SetTxContext(tx.Hash(), idx)
|
||||
// nolint : contextcheck
|
||||
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)
|
||||
}
|
||||
|
|
@ -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
|
||||
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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ func (h *handler) doSync(op *chainSyncOp) error {
|
|||
atomic.StoreUint32(&h.acceptTxs, 1)
|
||||
}
|
||||
}
|
||||
|
||||
if head.Number.Uint64() > 0 {
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -288,15 +288,18 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
|
|||
if !supported {
|
||||
return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
|
||||
}
|
||||
|
||||
sub := notifier.CreateSubscription()
|
||||
|
||||
// nolint : contextcheck
|
||||
resCh := api.traceChain(from, to, config, notifier.Closed())
|
||||
|
||||
go func() {
|
||||
for result := range resCh {
|
||||
notifier.Notify(sub.ID, result)
|
||||
}
|
||||
}()
|
||||
|
||||
return sub, nil
|
||||
}
|
||||
|
||||
|
|
@ -350,6 +353,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
|||
txs = txs[:len(txs)-1]
|
||||
stateSyncPresent = false
|
||||
}
|
||||
|
||||
for i, tx := range task.block.Transactions() {
|
||||
msg, _ := core.TransactionToMessage(tx, signer, task.block.BaseFee())
|
||||
txctx := &Context{
|
||||
|
|
@ -421,6 +425,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
|||
default:
|
||||
log.Info("Chain tracing finished", "start", start.NumberU64(), "end", end.NumberU64(), "transactions", traced, "elapsed", time.Since(begin))
|
||||
}
|
||||
|
||||
close(resCh)
|
||||
}()
|
||||
// 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
|
||||
break
|
||||
}
|
||||
|
||||
next, err := api.blockByNumber(ctx, rpc.BlockNumber(number+1))
|
||||
if err != nil {
|
||||
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
|
||||
// if the relevant state is available in disk.
|
||||
var preferDisk bool
|
||||
|
||||
if statedb != nil {
|
||||
s1, s2 := statedb.Database().TrieDB().Size()
|
||||
preferDisk = s1+s2 > defaultTracechainMemLimit
|
||||
}
|
||||
|
||||
statedb, release, err = api.backend.StateAtBlock(ctx, block, reexec, statedb, false, preferDisk)
|
||||
if err != nil {
|
||||
failed = err
|
||||
|
|
@ -495,6 +503,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
|||
next = start.NumberU64() + 1
|
||||
done = make(map[uint64]*blockTraceResult)
|
||||
)
|
||||
|
||||
for res := range resCh {
|
||||
// Queue up next received result
|
||||
result := &blockTraceResult{
|
||||
|
|
@ -518,6 +527,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
|
|||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return retCh
|
||||
}
|
||||
|
||||
|
|
@ -636,10 +646,12 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
|||
if config != nil && config.Reexec != nil {
|
||||
reexec = *config.Reexec
|
||||
}
|
||||
|
||||
statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
var (
|
||||
|
|
@ -660,6 +672,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
|||
txContext = core.NewEVMTxContext(msg)
|
||||
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
||||
)
|
||||
|
||||
statedb.SetTxContext(tx.Hash(), i)
|
||||
//nolint: nestif
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
// 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) {
|
||||
threads = len(txs)
|
||||
}
|
||||
|
||||
jobs := make(chan *txTraceTask, threads)
|
||||
for th := 0; th < threads; th++ {
|
||||
pend.Add(1)
|
||||
|
|
@ -982,10 +997,12 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
|||
if config != nil && config.Reexec != nil {
|
||||
reexec = *config.Reexec
|
||||
}
|
||||
|
||||
statedb, release, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
// Retrieve the tracing configurations, or use default values
|
||||
|
|
@ -1040,6 +1057,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
|||
if !canon {
|
||||
prefix = fmt.Sprintf("%valt-", prefix)
|
||||
}
|
||||
|
||||
dump, err = os.CreateTemp(os.TempDir(), prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -1143,10 +1161,12 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg, vmctx, statedb, release, err := api.backend.StateAtTransaction(ctx, block, int(index), reexec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
txctx := &Context{
|
||||
|
|
@ -1190,18 +1210,22 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
|||
if config != nil && config.Reexec != nil {
|
||||
reexec = *config.Reexec
|
||||
}
|
||||
|
||||
statedb, release, err := api.backend.StateAtBlock(ctx, block, reexec, nil, true, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
vmctx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||
|
||||
// Apply the customization rules if required.
|
||||
if config != nil {
|
||||
if err := config.StateOverrides.Apply(statedb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config.BlockOverrides.Apply(&vmctx)
|
||||
}
|
||||
// Execute the trace
|
||||
|
|
@ -1238,6 +1262,7 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
|
|||
timeout = defaultTraceTimeout
|
||||
txContext = core.NewEVMTxContext(message)
|
||||
)
|
||||
|
||||
if config == nil {
|
||||
config = &TraceConfig{}
|
||||
}
|
||||
|
|
@ -1249,6 +1274,7 @@ func (api *API) traceTx(ctx context.Context, message *core.Message, txctx *Conte
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer, NoBaseFee: true})
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
deadlineCtx, cancel := context.WithTimeout(ctx, timeout)
|
||||
|
||||
go func() {
|
||||
<-deadlineCtx.Done()
|
||||
|
||||
if errors.Is(deadlineCtx.Err(), context.DeadlineExceeded) {
|
||||
tracer.Stop(errors.New("execution timeout"))
|
||||
// Stop evm execution. Note cancellation is not necessarily immediate.
|
||||
vmenv.Cancel()
|
||||
}
|
||||
}()
|
||||
|
||||
defer cancel()
|
||||
|
||||
// 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 tracer.GetResult()
|
||||
}
|
||||
|
||||
|
|
@ -1314,30 +1345,37 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig)
|
|||
chainConfigCopy.BerlinBlock = block
|
||||
canon = false
|
||||
}
|
||||
|
||||
if block := override.LondonBlock; block != nil {
|
||||
chainConfigCopy.LondonBlock = block
|
||||
canon = false
|
||||
}
|
||||
|
||||
if block := override.ArrowGlacierBlock; block != nil {
|
||||
chainConfigCopy.ArrowGlacierBlock = block
|
||||
canon = false
|
||||
}
|
||||
|
||||
if block := override.GrayGlacierBlock; block != nil {
|
||||
chainConfigCopy.GrayGlacierBlock = block
|
||||
canon = false
|
||||
}
|
||||
|
||||
if block := override.MergeNetsplitBlock; block != nil {
|
||||
chainConfigCopy.MergeNetsplitBlock = block
|
||||
canon = false
|
||||
}
|
||||
|
||||
if timestamp := override.ShanghaiTime; timestamp != nil {
|
||||
chainConfigCopy.ShanghaiTime = timestamp
|
||||
canon = false
|
||||
}
|
||||
|
||||
if timestamp := override.CancunTime; timestamp != nil {
|
||||
chainConfigCopy.CancunTime = timestamp
|
||||
canon = false
|
||||
}
|
||||
|
||||
if timestamp := override.PragueTime; timestamp != nil {
|
||||
chainConfigCopy.PragueTime = timestamp
|
||||
canon = false
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer release()
|
||||
|
||||
// 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
Loading…
Reference in a new issue