mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
Merge remote-tracking branch 'upstream/master' into vm-mempool
This commit is contained in:
commit
b98528258a
88 changed files with 708 additions and 665 deletions
|
|
@ -64,10 +64,6 @@ issues:
|
||||||
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
text: 'SA1019: "golang.org/x/crypto/openpgp" is deprecated: this package is unmaintained except for security fixes.'
|
||||||
- path: core/vm/contracts.go
|
- path: core/vm/contracts.go
|
||||||
text: 'SA1019: "golang.org/x/crypto/ripemd160" is deprecated: RIPEMD-160 is a legacy hash and should not be used for new applications.'
|
text: 'SA1019: "golang.org/x/crypto/ripemd160" is deprecated: RIPEMD-160 is a legacy hash and should not be used for new applications.'
|
||||||
- path: accounts/usbwallet/trezor.go
|
|
||||||
text: 'SA1019: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead.'
|
|
||||||
- path: accounts/usbwallet/trezor/
|
|
||||||
text: 'SA1019: "github.com/golang/protobuf/proto" is deprecated: Use the "google.golang.org/protobuf/proto" package instead.'
|
|
||||||
exclude:
|
exclude:
|
||||||
- 'SA1019: event.TypeMux is deprecated: use Feed'
|
- 'SA1019: event.TypeMux is deprecated: use Feed'
|
||||||
- 'SA1019: strings.Title is deprecated'
|
- 'SA1019: strings.Title is deprecated'
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -42,7 +42,7 @@ clean:
|
||||||
devtools:
|
devtools:
|
||||||
env GOBIN= go install golang.org/x/tools/cmd/stringer@latest
|
env GOBIN= go install golang.org/x/tools/cmd/stringer@latest
|
||||||
env GOBIN= go install github.com/fjl/gencodec@latest
|
env GOBIN= go install github.com/fjl/gencodec@latest
|
||||||
env GOBIN= go install github.com/golang/protobuf/protoc-gen-go@latest
|
env GOBIN= go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||||
env GOBIN= go install ./cmd/abigen
|
env GOBIN= go install ./cmd/abigen
|
||||||
@type "solc" 2> /dev/null || echo 'Please install solc'
|
@type "solc" 2> /dev/null || echo 'Please install solc'
|
||||||
@type "protoc" 2> /dev/null || echo 'Please install protoc'
|
@type "protoc" 2> /dev/null || echo 'Please install protoc'
|
||||||
|
|
|
||||||
|
|
@ -171,5 +171,5 @@ i4O1UeWKs9owWttan9+PI47ozBSKOTxmMqLSQ0f56Np9FJsV0ilGxRKfjhzJ4KniOMUBA7mP
|
||||||
epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx
|
epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx
|
||||||
PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano=
|
PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano=
|
||||||
=arte
|
=arte
|
||||||
-----END PGP PUBLIC KEY BLOCK------
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,12 @@ type TransactOpts struct {
|
||||||
Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state)
|
Nonce *big.Int // Nonce to use for the transaction execution (nil = use pending state)
|
||||||
Signer SignerFn // Method to use for signing the transaction (mandatory)
|
Signer SignerFn // Method to use for signing the transaction (mandatory)
|
||||||
|
|
||||||
Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds)
|
Value *big.Int // Funds to transfer along the transaction (nil = 0 = no funds)
|
||||||
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
|
GasPrice *big.Int // Gas price to use for the transaction execution (nil = gas price oracle)
|
||||||
GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle)
|
GasFeeCap *big.Int // Gas fee cap to use for the 1559 transaction execution (nil = gas price oracle)
|
||||||
GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle)
|
GasTipCap *big.Int // Gas priority fee cap to use for the 1559 transaction execution (nil = gas price oracle)
|
||||||
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
|
GasLimit uint64 // Gas limit to set for the transaction execution (0 = estimate)
|
||||||
|
AccessList types.AccessList // Access list to set for the transaction execution (nil = no access list)
|
||||||
|
|
||||||
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
|
||||||
|
|
||||||
|
|
@ -300,20 +301,21 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
baseTx := &types.DynamicFeeTx{
|
baseTx := &types.DynamicFeeTx{
|
||||||
To: contract,
|
To: contract,
|
||||||
Nonce: nonce,
|
Nonce: nonce,
|
||||||
GasFeeCap: gasFeeCap,
|
GasFeeCap: gasFeeCap,
|
||||||
GasTipCap: gasTipCap,
|
GasTipCap: gasTipCap,
|
||||||
Gas: gasLimit,
|
Gas: gasLimit,
|
||||||
Value: value,
|
Value: value,
|
||||||
Data: input,
|
Data: input,
|
||||||
|
AccessList: opts.AccessList,
|
||||||
}
|
}
|
||||||
return types.NewTx(baseTx), nil
|
return types.NewTx(baseTx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
|
func (c *BoundContract) createLegacyTx(opts *TransactOpts, contract *common.Address, input []byte) (*types.Transaction, error) {
|
||||||
if opts.GasFeeCap != nil || opts.GasTipCap != nil {
|
if opts.GasFeeCap != nil || opts.GasTipCap != nil || opts.AccessList != nil {
|
||||||
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas specified but london is not active yet")
|
return nil, errors.New("maxFeePerGas or maxPriorityFeePerGas or accessList specified but london is not active yet")
|
||||||
}
|
}
|
||||||
// Normalize value
|
// Normalize value
|
||||||
value := opts.Value
|
value := opts.Value
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ func TestWatchNewFile(t *testing.T) {
|
||||||
func TestWatchNoDir(t *testing.T) {
|
func TestWatchNoDir(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
// Create ks but not the directory that it watches.
|
// Create ks but not the directory that it watches.
|
||||||
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int()))
|
dir := filepath.Join(t.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int()))
|
||||||
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
|
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
|
||||||
list := ks.Accounts()
|
list := ks.Accounts()
|
||||||
if len(list) > 0 {
|
if len(list) > 0 {
|
||||||
|
|
@ -126,7 +126,6 @@ func TestWatchNoDir(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Create the directory and copy a key file into it.
|
// Create the directory and copy a key file into it.
|
||||||
os.MkdirAll(dir, 0700)
|
os.MkdirAll(dir, 0700)
|
||||||
defer os.RemoveAll(dir)
|
|
||||||
file := filepath.Join(dir, "aaa")
|
file := filepath.Join(dir, "aaa")
|
||||||
if err := cp.CopyFile(file, cachetestAccounts[0].URL.Path); err != nil {
|
if err := cp.CopyFile(file, cachetestAccounts[0].URL.Path); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/golang/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In
|
// ErrTrezorPINNeeded is returned if opening the trezor requires a PIN code. In
|
||||||
|
|
|
||||||
|
|
@ -39,8 +39,8 @@
|
||||||
// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
|
// - Download the latest protoc https://github.com/protocolbuffers/protobuf/releases
|
||||||
// - Build with the usual `./configure && make` and ensure it's on your $PATH
|
// - Build with the usual `./configure && make` and ensure it's on your $PATH
|
||||||
// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
|
// - Delete all the .proto and .pb.go files, pull in fresh ones from Trezor
|
||||||
// - Grab the latest Go plugin `go get -u github.com/golang/protobuf/protoc-gen-go`
|
// - Grab the latest Go plugin `go get -u google.golang.org/protobuf/cmd/protoc-gen-go`
|
||||||
// - Vendor in the latest Go plugin `govendor fetch github.com/golang/protobuf/...`
|
// - Vendor in the latest Go plugin `govendor fetch google.golang.org/protobuf/...`
|
||||||
|
|
||||||
//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
|
//go:generate protoc -I/usr/local/include:. --go_out=paths=source_relative:. messages.proto messages-common.proto messages-management.proto messages-ethereum.proto
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ package trezor
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Type returns the protocol buffer type number of a specific message. If the
|
// Type returns the protocol buffer type number of a specific message. If the
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func BlockFromJSON(forkName string, data []byte) (*BeaconBlock, error) {
|
||||||
case "capella":
|
case "capella":
|
||||||
obj = new(capella.BeaconBlock)
|
obj = new(capella.BeaconBlock)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported fork: " + forkName)
|
return nil, fmt.Errorf("unsupported fork: %s", forkName)
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(data, obj); err != nil {
|
if err := json.Unmarshal(data, obj); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ func ExecutionHeaderFromJSON(forkName string, data []byte) (*ExecutionHeader, er
|
||||||
case "deneb":
|
case "deneb":
|
||||||
obj = new(deneb.ExecutionPayloadHeader)
|
obj = new(deneb.ExecutionPayloadHeader)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported fork: " + forkName)
|
return nil, fmt.Errorf("unsupported fork: %s", forkName)
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(data, obj); err != nil {
|
if err := json.Unmarshal(data, obj); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,6 @@ package tools
|
||||||
import (
|
import (
|
||||||
// Tool imports for go:generate.
|
// Tool imports for go:generate.
|
||||||
_ "github.com/fjl/gencodec"
|
_ "github.com/fjl/gencodec"
|
||||||
_ "github.com/golang/protobuf/protoc-gen-go"
|
|
||||||
_ "golang.org/x/tools/cmd/stringer"
|
_ "golang.org/x/tools/cmd/stringer"
|
||||||
|
_ "google.golang.org/protobuf/cmd/protoc-gen-go"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,8 @@ import (
|
||||||
// TestImportRaw tests clef --importraw
|
// TestImportRaw tests clef --importraw
|
||||||
func TestImportRaw(t *testing.T) {
|
func TestImportRaw(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||||
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
||||||
t.Cleanup(func() { os.Remove(keyPath) })
|
|
||||||
|
|
||||||
t.Run("happy-path", func(t *testing.T) {
|
t.Run("happy-path", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -68,9 +67,8 @@ func TestImportRaw(t *testing.T) {
|
||||||
// TestListAccounts tests clef --list-accounts
|
// TestListAccounts tests clef --list-accounts
|
||||||
func TestListAccounts(t *testing.T) {
|
func TestListAccounts(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||||
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
||||||
t.Cleanup(func() { os.Remove(keyPath) })
|
|
||||||
|
|
||||||
t.Run("no-accounts", func(t *testing.T) {
|
t.Run("no-accounts", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -97,9 +95,8 @@ func TestListAccounts(t *testing.T) {
|
||||||
// TestListWallets tests clef --list-wallets
|
// TestListWallets tests clef --list-wallets
|
||||||
func TestListWallets(t *testing.T) {
|
func TestListWallets(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||||
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
||||||
t.Cleanup(func() { os.Remove(keyPath) })
|
|
||||||
|
|
||||||
t.Run("no-accounts", func(t *testing.T) {
|
t.Run("no-accounts", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
|
||||||
|
|
@ -34,12 +34,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeJWTSecret() (string, [32]byte, error) {
|
func makeJWTSecret(t *testing.T) (string, [32]byte, error) {
|
||||||
var secret [32]byte
|
var secret [32]byte
|
||||||
if _, err := crand.Read(secret[:]); err != nil {
|
if _, err := crand.Read(secret[:]); err != nil {
|
||||||
return "", secret, fmt.Errorf("failed to create jwt secret: %v", err)
|
return "", secret, fmt.Errorf("failed to create jwt secret: %v", err)
|
||||||
}
|
}
|
||||||
jwtPath := filepath.Join(os.TempDir(), "jwt_secret")
|
jwtPath := filepath.Join(t.TempDir(), "jwt_secret")
|
||||||
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
|
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
|
||||||
return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err)
|
return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ func makeJWTSecret() (string, [32]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEthSuite(t *testing.T) {
|
func TestEthSuite(t *testing.T) {
|
||||||
jwtPath, secret, err := makeJWTSecret()
|
jwtPath, secret, err := makeJWTSecret(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not make jwt secret: %v", err)
|
t.Fatalf("could not make jwt secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -75,7 +75,7 @@ func TestEthSuite(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnapSuite(t *testing.T) {
|
func TestSnapSuite(t *testing.T) {
|
||||||
jwtPath, secret, err := makeJWTSecret()
|
jwtPath, secret, err := makeJWTSecret(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not make jwt secret: %v", err)
|
t.Fatalf("could not make jwt secret: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ func rlpxPing(ctx *cli.Context) error {
|
||||||
n := getNodeArg(ctx)
|
n := getNodeArg(ctx)
|
||||||
tcpEndpoint, ok := n.TCPEndpoint()
|
tcpEndpoint, ok := n.TCPEndpoint()
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("node has no TCP endpoint")
|
return errors.New("node has no TCP endpoint")
|
||||||
}
|
}
|
||||||
fd, err := net.Dial("tcp", tcpEndpoint.String())
|
fd, err := net.Dial("tcp", tcpEndpoint.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,6 @@ func runCmd(ctx *cli.Context) error {
|
||||||
if ctx.String(SenderFlag.Name) != "" {
|
if ctx.String(SenderFlag.Name) != "" {
|
||||||
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
sender = common.HexToAddress(ctx.String(SenderFlag.Name))
|
||||||
}
|
}
|
||||||
statedb.CreateAccount(sender)
|
|
||||||
|
|
||||||
if ctx.String(ReceiverFlag.Name) != "" {
|
if ctx.String(ReceiverFlag.Name) != "" {
|
||||||
receiver = common.HexToAddress(ctx.String(ReceiverFlag.Name))
|
receiver = common.HexToAddress(ctx.String(ReceiverFlag.Name))
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,8 @@ func removeDB(ctx *cli.Context) error {
|
||||||
// Delete state data
|
// Delete state data
|
||||||
statePaths := []string{
|
statePaths := []string{
|
||||||
rootDir,
|
rootDir,
|
||||||
filepath.Join(ancientDir, rawdb.StateFreezerName),
|
filepath.Join(ancientDir, rawdb.MerkleStateFreezerName),
|
||||||
|
filepath.Join(ancientDir, rawdb.VerkleStateFreezerName),
|
||||||
}
|
}
|
||||||
confirmAndRemoveDB(statePaths, "state data", ctx, removeStateDataFlag.Name)
|
confirmAndRemoveDB(statePaths, "state data", ctx, removeStateDataFlag.Name)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,7 @@ import (
|
||||||
// TestExport does a basic test of "geth export", exporting the test-genesis.
|
// TestExport does a basic test of "geth export", exporting the test-genesis.
|
||||||
func TestExport(t *testing.T) {
|
func TestExport(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
outfile := fmt.Sprintf("%v/testExport.out", os.TempDir())
|
outfile := fmt.Sprintf("%v/testExport.out", t.TempDir())
|
||||||
defer os.Remove(outfile)
|
|
||||||
geth := runGeth(t, "--datadir", initGeth(t), "export", outfile)
|
geth := runGeth(t, "--datadir", initGeth(t), "export", outfile)
|
||||||
geth.WaitExit()
|
geth.WaitExit()
|
||||||
if have, want := geth.ExitStatus(), 0; have != want {
|
if have, want := geth.ExitStatus(), 0; have != want {
|
||||||
|
|
|
||||||
|
|
@ -201,9 +201,8 @@ func TestFileOut(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
have, want []byte
|
have, want []byte
|
||||||
err error
|
err error
|
||||||
path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
|
path = fmt.Sprintf("%s/test_file_out-%d", t.TempDir(), rand.Int63())
|
||||||
)
|
)
|
||||||
t.Cleanup(func() { os.Remove(path) })
|
|
||||||
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "logtest"); err != nil {
|
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "logtest"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -222,9 +221,8 @@ func TestRotatingFileOut(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
have, want []byte
|
have, want []byte
|
||||||
err error
|
err error
|
||||||
path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
|
path = fmt.Sprintf("%s/test_file_out-%d", t.TempDir(), rand.Int63())
|
||||||
)
|
)
|
||||||
t.Cleanup(func() { os.Remove(path) })
|
|
||||||
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "--log.rotate", "logtest"); err != nil {
|
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "--log.rotate", "logtest"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -360,8 +360,6 @@ func geth(ctx *cli.Context) error {
|
||||||
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
|
// it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
|
||||||
// miner.
|
// miner.
|
||||||
func startNode(ctx *cli.Context, stack *node.Node, isConsole bool) {
|
func startNode(ctx *cli.Context, stack *node.Node, isConsole bool) {
|
||||||
debug.Memsize.Add("node", stack)
|
|
||||||
|
|
||||||
// Start up the node itself
|
// Start up the node itself
|
||||||
utils.StartNode(ctx, stack, isConsole)
|
utils.StartNode(ctx, stack, isConsole)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,18 +29,12 @@ import (
|
||||||
|
|
||||||
// TestExport does basic sanity checks on the export/import functionality
|
// TestExport does basic sanity checks on the export/import functionality
|
||||||
func TestExport(t *testing.T) {
|
func TestExport(t *testing.T) {
|
||||||
f := fmt.Sprintf("%v/tempdump", os.TempDir())
|
f := fmt.Sprintf("%v/tempdump", t.TempDir())
|
||||||
defer func() {
|
|
||||||
os.Remove(f)
|
|
||||||
}()
|
|
||||||
testExport(t, f)
|
testExport(t, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExportGzip(t *testing.T) {
|
func TestExportGzip(t *testing.T) {
|
||||||
f := fmt.Sprintf("%v/tempdump.gz", os.TempDir())
|
f := fmt.Sprintf("%v/tempdump.gz", t.TempDir())
|
||||||
defer func() {
|
|
||||||
os.Remove(f)
|
|
||||||
}()
|
|
||||||
testExport(t, f)
|
testExport(t, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,20 +93,14 @@ func testExport(t *testing.T, f string) {
|
||||||
|
|
||||||
// TestDeletionExport tests if the deletion markers can be exported/imported correctly
|
// TestDeletionExport tests if the deletion markers can be exported/imported correctly
|
||||||
func TestDeletionExport(t *testing.T) {
|
func TestDeletionExport(t *testing.T) {
|
||||||
f := fmt.Sprintf("%v/tempdump", os.TempDir())
|
f := fmt.Sprintf("%v/tempdump", t.TempDir())
|
||||||
defer func() {
|
|
||||||
os.Remove(f)
|
|
||||||
}()
|
|
||||||
testDeletion(t, f)
|
testDeletion(t, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestDeletionExportGzip tests if the deletion markers can be exported/imported
|
// TestDeletionExportGzip tests if the deletion markers can be exported/imported
|
||||||
// correctly with gz compression.
|
// correctly with gz compression.
|
||||||
func TestDeletionExportGzip(t *testing.T) {
|
func TestDeletionExportGzip(t *testing.T) {
|
||||||
f := fmt.Sprintf("%v/tempdump.gz", os.TempDir())
|
f := fmt.Sprintf("%v/tempdump.gz", t.TempDir())
|
||||||
defer func() {
|
|
||||||
os.Remove(f)
|
|
||||||
}()
|
|
||||||
testDeletion(t, f)
|
testDeletion(t, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,10 +159,7 @@ func testDeletion(t *testing.T, f string) {
|
||||||
// TestImportFutureFormat tests that we reject unsupported future versions.
|
// TestImportFutureFormat tests that we reject unsupported future versions.
|
||||||
func TestImportFutureFormat(t *testing.T) {
|
func TestImportFutureFormat(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
f := fmt.Sprintf("%v/tempdump-future", os.TempDir())
|
f := fmt.Sprintf("%v/tempdump-future", t.TempDir())
|
||||||
defer func() {
|
|
||||||
os.Remove(f)
|
|
||||||
}()
|
|
||||||
fh, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
|
fh, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
|
"github.com/ethereum/go-ethereum/core/txpool/blobpool"
|
||||||
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
"github.com/ethereum/go-ethereum/core/txpool/legacypool"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
@ -291,7 +292,7 @@ var (
|
||||||
}
|
}
|
||||||
BeaconApiHeaderFlag = &cli.StringSliceFlag{
|
BeaconApiHeaderFlag = &cli.StringSliceFlag{
|
||||||
Name: "beacon.api.header",
|
Name: "beacon.api.header",
|
||||||
Usage: "Pass custom HTTP header fields to the emote beacon node API in \"key:value\" format. This flag can be given multiple times.",
|
Usage: "Pass custom HTTP header fields to the remote beacon node API in \"key:value\" format. This flag can be given multiple times.",
|
||||||
Category: flags.BeaconCategory,
|
Category: flags.BeaconCategory,
|
||||||
}
|
}
|
||||||
BeaconThresholdFlag = &cli.IntFlag{
|
BeaconThresholdFlag = &cli.IntFlag{
|
||||||
|
|
@ -1550,6 +1551,18 @@ func setTxPool(ctx *cli.Context, cfg *legacypool.Config) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setBlobPool(ctx *cli.Context, cfg *blobpool.Config) {
|
||||||
|
if ctx.IsSet(BlobPoolDataDirFlag.Name) {
|
||||||
|
cfg.Datadir = ctx.String(BlobPoolDataDirFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.IsSet(BlobPoolDataCapFlag.Name) {
|
||||||
|
cfg.Datacap = ctx.Uint64(BlobPoolDataCapFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.IsSet(BlobPoolPriceBumpFlag.Name) {
|
||||||
|
cfg.PriceBump = ctx.Uint64(BlobPoolPriceBumpFlag.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
func setMiner(ctx *cli.Context, cfg *miner.Config) {
|
||||||
if ctx.Bool(MiningEnabledFlag.Name) {
|
if ctx.Bool(MiningEnabledFlag.Name) {
|
||||||
log.Warn("The flag --mine is deprecated and will be removed")
|
log.Warn("The flag --mine is deprecated and will be removed")
|
||||||
|
|
@ -1651,6 +1664,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
setEtherbase(ctx, cfg)
|
setEtherbase(ctx, cfg)
|
||||||
setGPO(ctx, &cfg.GPO)
|
setGPO(ctx, &cfg.GPO)
|
||||||
setTxPool(ctx, &cfg.TxPool)
|
setTxPool(ctx, &cfg.TxPool)
|
||||||
|
setBlobPool(ctx, &cfg.BlobPool)
|
||||||
setMiner(ctx, &cfg.Miner)
|
setMiner(ctx, &cfg.Miner)
|
||||||
setRequiredBlocks(ctx, cfg)
|
setRequiredBlocks(ctx, cfg)
|
||||||
setLes(ctx, cfg)
|
setLes(ctx, cfg)
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
triedb := triedb.NewDatabase(db, &triedb.Config{IsVerkle: true, PathDB: pathdb.Defaults})
|
triedb := triedb.NewDatabase(db, triedb.VerkleDefaults)
|
||||||
block := genesis.MustCommit(db, triedb)
|
block := genesis.MustCommit(db, triedb)
|
||||||
if !bytes.Equal(block.Root().Bytes(), expected) {
|
if !bytes.Equal(block.Root().Bytes(), expected) {
|
||||||
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root())
|
t.Fatalf("invalid genesis state root, expected %x, got %x", expected, block.Root())
|
||||||
|
|
@ -321,8 +321,8 @@ func TestVerkleGenesisCommit(t *testing.T) {
|
||||||
if !triedb.IsVerkle() {
|
if !triedb.IsVerkle() {
|
||||||
t.Fatalf("expected trie to be verkle")
|
t.Fatalf("expected trie to be verkle")
|
||||||
}
|
}
|
||||||
|
vdb := rawdb.NewTable(db, string(rawdb.VerklePrefix))
|
||||||
if !rawdb.HasAccountTrieNode(db, nil) {
|
if !rawdb.HasAccountTrieNode(vdb, nil) {
|
||||||
t.Fatal("could not find node")
|
t.Fatal("could not find node")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ func DeleteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, has
|
||||||
|
|
||||||
// ReadStateScheme reads the state scheme of persistent state, or none
|
// ReadStateScheme reads the state scheme of persistent state, or none
|
||||||
// if the state is not present in database.
|
// if the state is not present in database.
|
||||||
func ReadStateScheme(db ethdb.Reader) string {
|
func ReadStateScheme(db ethdb.Database) string {
|
||||||
// Check if state in path-based scheme is present.
|
// Check if state in path-based scheme is present.
|
||||||
if HasAccountTrieNode(db, nil) {
|
if HasAccountTrieNode(db, nil) {
|
||||||
return PathScheme
|
return PathScheme
|
||||||
|
|
@ -255,6 +255,16 @@ func ReadStateScheme(db ethdb.Reader) string {
|
||||||
if id := ReadPersistentStateID(db); id != 0 {
|
if id := ReadPersistentStateID(db); id != 0 {
|
||||||
return PathScheme
|
return PathScheme
|
||||||
}
|
}
|
||||||
|
// Check if verkle state in path-based scheme is present.
|
||||||
|
vdb := NewTable(db, string(VerklePrefix))
|
||||||
|
if HasAccountTrieNode(vdb, nil) {
|
||||||
|
return PathScheme
|
||||||
|
}
|
||||||
|
// The root node of verkle might be deleted during the initial snap sync,
|
||||||
|
// check the persistent state id then.
|
||||||
|
if id := ReadPersistentStateID(vdb); id != 0 {
|
||||||
|
return PathScheme
|
||||||
|
}
|
||||||
// In a hash-based scheme, the genesis state is consistently stored
|
// In a hash-based scheme, the genesis state is consistently stored
|
||||||
// on the disk. To assess the scheme of the persistent state, it
|
// on the disk. To assess the scheme of the persistent state, it
|
||||||
// suffices to inspect the scheme of the genesis state.
|
// suffices to inspect the scheme of the genesis state.
|
||||||
|
|
|
||||||
|
|
@ -72,12 +72,13 @@ var stateFreezerNoSnappy = map[string]bool{
|
||||||
|
|
||||||
// The list of identifiers of ancient stores.
|
// The list of identifiers of ancient stores.
|
||||||
var (
|
var (
|
||||||
ChainFreezerName = "chain" // the folder name of chain segment ancient store.
|
ChainFreezerName = "chain" // the folder name of chain segment ancient store.
|
||||||
StateFreezerName = "state" // the folder name of reverse diff ancient store.
|
MerkleStateFreezerName = "state" // the folder name of state history ancient store.
|
||||||
|
VerkleStateFreezerName = "state_verkle" // the folder name of state history ancient store.
|
||||||
)
|
)
|
||||||
|
|
||||||
// freezers the collections of all builtin freezers.
|
// freezers the collections of all builtin freezers.
|
||||||
var freezers = []string{ChainFreezerName, StateFreezerName}
|
var freezers = []string{ChainFreezerName, MerkleStateFreezerName, VerkleStateFreezerName}
|
||||||
|
|
||||||
// NewStateFreezer initializes the ancient store for state history.
|
// NewStateFreezer initializes the ancient store for state history.
|
||||||
//
|
//
|
||||||
|
|
@ -85,9 +86,15 @@ var freezers = []string{ChainFreezerName, StateFreezerName}
|
||||||
// state freezer (e.g. dev mode).
|
// state freezer (e.g. dev mode).
|
||||||
// - if non-empty directory is given, initializes the regular file-based
|
// - if non-empty directory is given, initializes the regular file-based
|
||||||
// state freezer.
|
// state freezer.
|
||||||
func NewStateFreezer(ancientDir string, readOnly bool) (ethdb.ResettableAncientStore, error) {
|
func NewStateFreezer(ancientDir string, verkle bool, readOnly bool) (ethdb.ResettableAncientStore, error) {
|
||||||
if ancientDir == "" {
|
if ancientDir == "" {
|
||||||
return NewMemoryFreezer(readOnly, stateFreezerNoSnappy), nil
|
return NewMemoryFreezer(readOnly, stateFreezerNoSnappy), nil
|
||||||
}
|
}
|
||||||
return newResettableFreezer(filepath.Join(ancientDir, StateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
|
var name string
|
||||||
|
if verkle {
|
||||||
|
name = filepath.Join(ancientDir, VerkleStateFreezerName)
|
||||||
|
} else {
|
||||||
|
name = filepath.Join(ancientDir, MerkleStateFreezerName)
|
||||||
|
}
|
||||||
|
return newResettableFreezer(name, "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,12 +88,12 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||||
}
|
}
|
||||||
infos = append(infos, info)
|
infos = append(infos, info)
|
||||||
|
|
||||||
case StateFreezerName:
|
case MerkleStateFreezerName, VerkleStateFreezerName:
|
||||||
datadir, err := db.AncientDatadir()
|
datadir, err := db.AncientDatadir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
f, err := NewStateFreezer(datadir, true)
|
f, err := NewStateFreezer(datadir, freezer == VerkleStateFreezerName, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue // might be possible the state freezer is not existent
|
continue // might be possible the state freezer is not existent
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +124,7 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
|
||||||
switch freezerName {
|
switch freezerName {
|
||||||
case ChainFreezerName:
|
case ChainFreezerName:
|
||||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||||
case StateFreezerName:
|
case MerkleStateFreezerName, VerkleStateFreezerName:
|
||||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||||
|
|
|
||||||
|
|
@ -481,6 +481,10 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||||
beaconHeaders stat
|
beaconHeaders stat
|
||||||
cliqueSnaps stat
|
cliqueSnaps stat
|
||||||
|
|
||||||
|
// Verkle statistics
|
||||||
|
verkleTries stat
|
||||||
|
verkleStateLookups stat
|
||||||
|
|
||||||
// Les statistic
|
// Les statistic
|
||||||
chtTrieNodes stat
|
chtTrieNodes stat
|
||||||
bloomTrieNodes stat
|
bloomTrieNodes stat
|
||||||
|
|
@ -550,6 +554,24 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||||
bytes.HasPrefix(key, BloomTrieIndexPrefix) ||
|
bytes.HasPrefix(key, BloomTrieIndexPrefix) ||
|
||||||
bytes.HasPrefix(key, BloomTriePrefix): // Bloomtrie sub
|
bytes.HasPrefix(key, BloomTriePrefix): // Bloomtrie sub
|
||||||
bloomTrieNodes.Add(size)
|
bloomTrieNodes.Add(size)
|
||||||
|
|
||||||
|
// Verkle trie data is detected, determine the sub-category
|
||||||
|
case bytes.HasPrefix(key, VerklePrefix):
|
||||||
|
remain := key[len(VerklePrefix):]
|
||||||
|
switch {
|
||||||
|
case IsAccountTrieNode(remain):
|
||||||
|
verkleTries.Add(size)
|
||||||
|
case bytes.HasPrefix(remain, stateIDPrefix) && len(remain) == len(stateIDPrefix)+common.HashLength:
|
||||||
|
verkleStateLookups.Add(size)
|
||||||
|
case bytes.Equal(remain, persistentStateIDKey):
|
||||||
|
metadata.Add(size)
|
||||||
|
case bytes.Equal(remain, trieJournalKey):
|
||||||
|
metadata.Add(size)
|
||||||
|
case bytes.Equal(remain, snapSyncStatusFlagKey):
|
||||||
|
metadata.Add(size)
|
||||||
|
default:
|
||||||
|
unaccounted.Add(size)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
var accounted bool
|
var accounted bool
|
||||||
for _, meta := range [][]byte{
|
for _, meta := range [][]byte{
|
||||||
|
|
@ -590,6 +612,8 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||||
{"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()},
|
{"Key-Value store", "Path trie state lookups", stateLookups.Size(), stateLookups.Count()},
|
||||||
{"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()},
|
{"Key-Value store", "Path trie account nodes", accountTries.Size(), accountTries.Count()},
|
||||||
{"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()},
|
{"Key-Value store", "Path trie storage nodes", storageTries.Size(), storageTries.Count()},
|
||||||
|
{"Key-Value store", "Verkle trie nodes", verkleTries.Size(), verkleTries.Count()},
|
||||||
|
{"Key-Value store", "Verkle trie state lookups", verkleStateLookups.Size(), verkleStateLookups.Count()},
|
||||||
{"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()},
|
{"Key-Value store", "Trie preimages", preimages.Size(), preimages.Count()},
|
||||||
{"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()},
|
{"Key-Value store", "Account snapshot", accountSnaps.Size(), accountSnaps.Count()},
|
||||||
{"Key-Value store", "Storage snapshot", storageSnaps.Size(), storageSnaps.Count()},
|
{"Key-Value store", "Storage snapshot", storageSnaps.Size(), storageSnaps.Count()},
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadWriteFreezerTableMeta(t *testing.T) {
|
func TestReadWriteFreezerTableMeta(t *testing.T) {
|
||||||
f, err := os.CreateTemp(os.TempDir(), "*")
|
f, err := os.CreateTemp(t.TempDir(), "*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create file %v", err)
|
t.Fatalf("Failed to create file %v", err)
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
err = writeMetadata(f, newMetadata(100))
|
err = writeMetadata(f, newMetadata(100))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to write metadata %v", err)
|
t.Fatalf("Failed to write metadata %v", err)
|
||||||
|
|
@ -43,10 +44,11 @@ func TestReadWriteFreezerTableMeta(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInitializeFreezerTableMeta(t *testing.T) {
|
func TestInitializeFreezerTableMeta(t *testing.T) {
|
||||||
f, err := os.CreateTemp(os.TempDir(), "*")
|
f, err := os.CreateTemp(t.TempDir(), "*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create file %v", err)
|
t.Fatalf("Failed to create file %v", err)
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
meta, err := loadMetadata(f, uint64(100))
|
meta, err := loadMetadata(f, uint64(100))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to read metadata %v", err)
|
t.Fatalf("Failed to read metadata %v", err)
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,13 @@ var (
|
||||||
TrieNodeStoragePrefix = []byte("O") // TrieNodeStoragePrefix + accountHash + hexPath -> trie node
|
TrieNodeStoragePrefix = []byte("O") // TrieNodeStoragePrefix + accountHash + hexPath -> trie node
|
||||||
stateIDPrefix = []byte("L") // stateIDPrefix + state root -> state id
|
stateIDPrefix = []byte("L") // stateIDPrefix + state root -> state id
|
||||||
|
|
||||||
|
// VerklePrefix is the database prefix for Verkle trie data, which includes:
|
||||||
|
// (a) Trie nodes
|
||||||
|
// (b) In-memory trie node journal
|
||||||
|
// (c) Persistent state ID
|
||||||
|
// (d) State ID lookups, etc.
|
||||||
|
VerklePrefix = []byte("v")
|
||||||
|
|
||||||
PreimagePrefix = []byte("secure-key-") // PreimagePrefix + hash -> preimage
|
PreimagePrefix = []byte("secure-key-") // PreimagePrefix + hash -> preimage
|
||||||
configPrefix = []byte("ethereum-config-") // config prefix for the db
|
configPrefix = []byte("ethereum-config-") // config prefix for the db
|
||||||
genesisPrefix = []byte("ethereum-genesis-") // genesis state prefix for the db
|
genesisPrefix = []byte("ethereum-genesis-") // genesis state prefix for the db
|
||||||
|
|
|
||||||
|
|
@ -200,13 +200,6 @@ func (t *table) NewBatchWithSize(size int) ethdb.Batch {
|
||||||
return &tableBatch{t.db.NewBatchWithSize(size), t.prefix}
|
return &tableBatch{t.db.NewBatchWithSize(size), t.prefix}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSnapshot creates a database snapshot based on the current state.
|
|
||||||
// The created snapshot will not be affected by all following mutations
|
|
||||||
// happened on the database.
|
|
||||||
func (t *table) NewSnapshot() (ethdb.Snapshot, error) {
|
|
||||||
return t.db.NewSnapshot()
|
|
||||||
}
|
|
||||||
|
|
||||||
// tableBatch is a wrapper around a database batch that prefixes each key access
|
// tableBatch is a wrapper around a database batch that prefixes each key access
|
||||||
// with a pre-configured string.
|
// with a pre-configured string.
|
||||||
type tableBatch struct {
|
type tableBatch struct {
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,4 @@ var (
|
||||||
storageTriesUpdatedMeter = metrics.NewRegisteredMeter("state/update/storagenodes", nil)
|
storageTriesUpdatedMeter = metrics.NewRegisteredMeter("state/update/storagenodes", nil)
|
||||||
accountTrieDeletedMeter = metrics.NewRegisteredMeter("state/delete/accountnodes", nil)
|
accountTrieDeletedMeter = metrics.NewRegisteredMeter("state/delete/accountnodes", nil)
|
||||||
storageTriesDeletedMeter = metrics.NewRegisteredMeter("state/delete/storagenodes", nil)
|
storageTriesDeletedMeter = metrics.NewRegisteredMeter("state/delete/storagenodes", nil)
|
||||||
|
|
||||||
slotDeletionMaxCount = metrics.NewRegisteredGauge("state/delete/storage/max/slot", nil)
|
|
||||||
slotDeletionMaxSize = metrics.NewRegisteredGauge("state/delete/storage/max/size", nil)
|
|
||||||
slotDeletionTimer = metrics.NewRegisteredResettingTimer("state/delete/storage/timer", nil)
|
|
||||||
slotDeletionCount = metrics.NewRegisteredMeter("state/delete/storage/slot", nil)
|
|
||||||
slotDeletionSize = metrics.NewRegisteredMeter("state/delete/storage/size", nil)
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -471,20 +471,28 @@ func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
|
||||||
// storage. This function should only be used for debugging and the mutations
|
// storage. This function should only be used for debugging and the mutations
|
||||||
// must be discarded afterwards.
|
// must be discarded afterwards.
|
||||||
func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
|
func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
|
||||||
// SetStorage needs to wipe existing storage. We achieve this by pretending
|
// SetStorage needs to wipe the existing storage. We achieve this by marking
|
||||||
// that the account self-destructed earlier in this block, by flagging
|
// the account as self-destructed in this block. The effect is that storage
|
||||||
// it in stateObjectsDestruct. The effect of doing so is that storage lookups
|
// lookups will not hit the disk, as it is assumed that the disk data belongs
|
||||||
// will not hit disk, since it is assumed that the disk-data is belonging
|
|
||||||
// to a previous incarnation of the object.
|
// to a previous incarnation of the object.
|
||||||
//
|
//
|
||||||
// TODO(rjl493456442) this function should only be supported by 'unwritable'
|
// TODO (rjl493456442): This function should only be supported by 'unwritable'
|
||||||
// state and all mutations made should all be discarded afterwards.
|
// state, and all mutations made should be discarded afterward.
|
||||||
if _, ok := s.stateObjectsDestruct[addr]; !ok {
|
obj := s.getStateObject(addr)
|
||||||
s.stateObjectsDestruct[addr] = nil
|
if obj != nil {
|
||||||
|
if _, ok := s.stateObjectsDestruct[addr]; !ok {
|
||||||
|
s.stateObjectsDestruct[addr] = obj
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stateObject := s.getOrNewStateObject(addr)
|
newObj := s.createObject(addr)
|
||||||
for k, v := range storage {
|
for k, v := range storage {
|
||||||
stateObject.SetState(k, v)
|
newObj.SetState(k, v)
|
||||||
|
}
|
||||||
|
// Inherit the metadata of original object if it was existent
|
||||||
|
if obj != nil {
|
||||||
|
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
|
||||||
|
newObj.SetNonce(obj.Nonce())
|
||||||
|
newObj.SetBalance(obj.Balance(), tracing.BalanceChangeUnspecified)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -860,12 +868,16 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
}
|
}
|
||||||
obj := s.stateObjects[addr] // closure for the task runner below
|
obj := s.stateObjects[addr] // closure for the task runner below
|
||||||
workers.Go(func() error {
|
workers.Go(func() error {
|
||||||
obj.updateRoot()
|
if s.db.TrieDB().IsVerkle() {
|
||||||
|
obj.updateTrie()
|
||||||
|
} else {
|
||||||
|
obj.updateRoot()
|
||||||
|
|
||||||
// If witness building is enabled and the state object has a trie,
|
// If witness building is enabled and the state object has a trie,
|
||||||
// gather the witnesses for its specific storage trie
|
// gather the witnesses for its specific storage trie
|
||||||
if s.witness != nil && obj.trie != nil {
|
if s.witness != nil && obj.trie != nil {
|
||||||
s.witness.AddState(obj.trie.Witness())
|
s.witness.AddState(obj.trie.Witness())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
@ -907,9 +919,12 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
|
||||||
// Now we're about to start to write changes to the trie. The trie is so far
|
// Now we're about to start to write changes to the trie. The trie is so far
|
||||||
// _untouched_. We can check with the prefetcher, if it can give us a trie
|
// _untouched_. We can check with the prefetcher, if it can give us a trie
|
||||||
// which has the same root, but also has some content loaded into it.
|
// which has the same root, but also has some content loaded into it.
|
||||||
|
//
|
||||||
|
// Don't check prefetcher if verkle trie has been used. In the context of verkle,
|
||||||
|
// only a single trie is used for state hashing. Replacing a non-nil verkle tree
|
||||||
|
// here could result in losing uncommitted changes from storage.
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
|
if s.prefetcher != nil && (s.trie == nil || !s.trie.IsVerkle()) {
|
||||||
if s.prefetcher != nil {
|
|
||||||
if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie == nil {
|
if trie := s.prefetcher.trie(common.Hash{}, s.originalRoot); trie == nil {
|
||||||
log.Error("Failed to retrieve account pre-fetcher trie")
|
log.Error("Failed to retrieve account pre-fetcher trie")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -985,76 +1000,70 @@ func (s *StateDB) clearJournalAndRefund() {
|
||||||
// of a specific account. It leverages the associated state snapshot for fast
|
// of a specific account. It leverages the associated state snapshot for fast
|
||||||
// storage iteration and constructs trie node deletion markers by creating
|
// storage iteration and constructs trie node deletion markers by creating
|
||||||
// stack trie with iterated slots.
|
// stack trie with iterated slots.
|
||||||
func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) {
|
func (s *StateDB) fastDeleteStorage(addrHash common.Hash, root common.Hash) (map[common.Hash][]byte, *trienode.NodeSet, error) {
|
||||||
iter, err := s.snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{})
|
iter, err := s.snaps.StorageIterator(s.originalRoot, addrHash, common.Hash{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
defer iter.Release()
|
defer iter.Release()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
size common.StorageSize
|
|
||||||
nodes = trienode.NewNodeSet(addrHash)
|
nodes = trienode.NewNodeSet(addrHash)
|
||||||
slots = make(map[common.Hash][]byte)
|
slots = make(map[common.Hash][]byte)
|
||||||
)
|
)
|
||||||
stack := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
|
stack := trie.NewStackTrie(func(path []byte, hash common.Hash, blob []byte) {
|
||||||
nodes.AddNode(path, trienode.NewDeleted())
|
nodes.AddNode(path, trienode.NewDeleted())
|
||||||
size += common.StorageSize(len(path))
|
|
||||||
})
|
})
|
||||||
for iter.Next() {
|
for iter.Next() {
|
||||||
slot := common.CopyBytes(iter.Slot())
|
slot := common.CopyBytes(iter.Slot())
|
||||||
if err := iter.Error(); err != nil { // error might occur after Slot function
|
if err := iter.Error(); err != nil { // error might occur after Slot function
|
||||||
return 0, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
size += common.StorageSize(common.HashLength + len(slot))
|
|
||||||
slots[iter.Hash()] = slot
|
slots[iter.Hash()] = slot
|
||||||
|
|
||||||
if err := stack.Update(iter.Hash().Bytes(), slot); err != nil {
|
if err := stack.Update(iter.Hash().Bytes(), slot); err != nil {
|
||||||
return 0, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := iter.Error(); err != nil { // error might occur during iteration
|
if err := iter.Error(); err != nil { // error might occur during iteration
|
||||||
return 0, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if stack.Hash() != root {
|
if stack.Hash() != root {
|
||||||
return 0, nil, nil, fmt.Errorf("snapshot is not matched, exp %x, got %x", root, stack.Hash())
|
return nil, nil, fmt.Errorf("snapshot is not matched, exp %x, got %x", root, stack.Hash())
|
||||||
}
|
}
|
||||||
return size, slots, nodes, nil
|
return slots, nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// slowDeleteStorage serves as a less-efficient alternative to "fastDeleteStorage,"
|
// slowDeleteStorage serves as a less-efficient alternative to "fastDeleteStorage,"
|
||||||
// employed when the associated state snapshot is not available. It iterates the
|
// employed when the associated state snapshot is not available. It iterates the
|
||||||
// storage slots along with all internal trie nodes via trie directly.
|
// storage slots along with all internal trie nodes via trie directly.
|
||||||
func (s *StateDB) slowDeleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (common.StorageSize, map[common.Hash][]byte, *trienode.NodeSet, error) {
|
func (s *StateDB) slowDeleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (map[common.Hash][]byte, *trienode.NodeSet, error) {
|
||||||
tr, err := s.db.OpenStorageTrie(s.originalRoot, addr, root, s.trie)
|
tr, err := s.db.OpenStorageTrie(s.originalRoot, addr, root, s.trie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, nil, fmt.Errorf("failed to open storage trie, err: %w", err)
|
return nil, nil, fmt.Errorf("failed to open storage trie, err: %w", err)
|
||||||
}
|
}
|
||||||
it, err := tr.NodeIterator(nil)
|
it, err := tr.NodeIterator(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, nil, fmt.Errorf("failed to open storage iterator, err: %w", err)
|
return nil, nil, fmt.Errorf("failed to open storage iterator, err: %w", err)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
size common.StorageSize
|
|
||||||
nodes = trienode.NewNodeSet(addrHash)
|
nodes = trienode.NewNodeSet(addrHash)
|
||||||
slots = make(map[common.Hash][]byte)
|
slots = make(map[common.Hash][]byte)
|
||||||
)
|
)
|
||||||
for it.Next(true) {
|
for it.Next(true) {
|
||||||
if it.Leaf() {
|
if it.Leaf() {
|
||||||
slots[common.BytesToHash(it.LeafKey())] = common.CopyBytes(it.LeafBlob())
|
slots[common.BytesToHash(it.LeafKey())] = common.CopyBytes(it.LeafBlob())
|
||||||
size += common.StorageSize(common.HashLength + len(it.LeafBlob()))
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if it.Hash() == (common.Hash{}) {
|
if it.Hash() == (common.Hash{}) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
size += common.StorageSize(len(it.Path()))
|
|
||||||
nodes.AddNode(it.Path(), trienode.NewDeleted())
|
nodes.AddNode(it.Path(), trienode.NewDeleted())
|
||||||
}
|
}
|
||||||
if err := it.Error(); err != nil {
|
if err := it.Error(); err != nil {
|
||||||
return 0, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return size, slots, nodes, nil
|
return slots, nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// deleteStorage is designed to delete the storage trie of a designated account.
|
// deleteStorage is designed to delete the storage trie of a designated account.
|
||||||
|
|
@ -1063,9 +1072,7 @@ func (s *StateDB) slowDeleteStorage(addr common.Address, addrHash common.Hash, r
|
||||||
// efficient approach.
|
// efficient approach.
|
||||||
func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (map[common.Hash][]byte, *trienode.NodeSet, error) {
|
func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root common.Hash) (map[common.Hash][]byte, *trienode.NodeSet, error) {
|
||||||
var (
|
var (
|
||||||
start = time.Now()
|
|
||||||
err error
|
err error
|
||||||
size common.StorageSize
|
|
||||||
slots map[common.Hash][]byte
|
slots map[common.Hash][]byte
|
||||||
nodes *trienode.NodeSet
|
nodes *trienode.NodeSet
|
||||||
)
|
)
|
||||||
|
|
@ -1073,24 +1080,14 @@ func (s *StateDB) deleteStorage(addr common.Address, addrHash common.Hash, root
|
||||||
// generated, or it's internally corrupted. Fallback to the slow
|
// generated, or it's internally corrupted. Fallback to the slow
|
||||||
// one just in case.
|
// one just in case.
|
||||||
if s.snap != nil {
|
if s.snap != nil {
|
||||||
size, slots, nodes, err = s.fastDeleteStorage(addrHash, root)
|
slots, nodes, err = s.fastDeleteStorage(addrHash, root)
|
||||||
}
|
}
|
||||||
if s.snap == nil || err != nil {
|
if s.snap == nil || err != nil {
|
||||||
size, slots, nodes, err = s.slowDeleteStorage(addr, addrHash, root)
|
slots, nodes, err = s.slowDeleteStorage(addr, addrHash, root)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
// Report the metrics
|
|
||||||
n := int64(len(slots))
|
|
||||||
|
|
||||||
slotDeletionMaxCount.UpdateIfGt(int64(len(slots)))
|
|
||||||
slotDeletionMaxSize.UpdateIfGt(int64(size))
|
|
||||||
|
|
||||||
slotDeletionTimer.UpdateSince(start)
|
|
||||||
slotDeletionCount.Mark(n)
|
|
||||||
slotDeletionSize.Mark(int64(size))
|
|
||||||
|
|
||||||
return slots, nodes, nil
|
return slots, nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1169,6 +1166,10 @@ func (s *StateDB) commit(deleteEmptyObjects bool) (*stateUpdate, error) {
|
||||||
// Finalize any pending changes and merge everything into the tries
|
// Finalize any pending changes and merge everything into the tries
|
||||||
s.IntermediateRoot(deleteEmptyObjects)
|
s.IntermediateRoot(deleteEmptyObjects)
|
||||||
|
|
||||||
|
// Short circuit if any error occurs within the IntermediateRoot.
|
||||||
|
if s.dbErr != nil {
|
||||||
|
return nil, fmt.Errorf("commit aborted due to database error: %v", s.dbErr)
|
||||||
|
}
|
||||||
// Commit objects to the trie, measuring the elapsed time
|
// Commit objects to the trie, measuring the elapsed time
|
||||||
var (
|
var (
|
||||||
accountTrieNodesUpdated int
|
accountTrieNodesUpdated int
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
All notable changes to the tracing interface will be documented in this file.
|
All notable changes to the tracing interface will be documented in this file.
|
||||||
|
|
||||||
## [Unreleased]
|
## [v1.14.3]
|
||||||
|
|
||||||
There have been minor backwards-compatible changes to the tracing interface to explicitly mark the execution of **system** contracts. As of now the only system call updates the parent beacon block root as per [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788). Other system calls are being considered for the future hardfork.
|
There have been minor backwards-compatible changes to the tracing interface to explicitly mark the execution of **system** contracts. As of now the only system call updates the parent beacon block root as per [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788). Other system calls are being considered for the future hardfork.
|
||||||
|
|
||||||
|
|
@ -77,3 +77,4 @@ The hooks `CaptureStart` and `CaptureEnd` have been removed. These hooks signale
|
||||||
|
|
||||||
[unreleased]: https://github.com/ethereum/go-ethereum/compare/v1.14.0...master
|
[unreleased]: https://github.com/ethereum/go-ethereum/compare/v1.14.0...master
|
||||||
[v1.14.0]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.0
|
[v1.14.0]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.0
|
||||||
|
[v1.14.3]: https://github.com/ethereum/go-ethereum/releases/tag/v1.14.3
|
||||||
|
|
|
||||||
|
|
@ -1116,7 +1116,7 @@ func (p *BlobPool) validateTx(tx *types.Transaction) error {
|
||||||
ExistingCost: func(addr common.Address, nonce uint64) *big.Int {
|
ExistingCost: func(addr common.Address, nonce uint64) *big.Int {
|
||||||
next := p.state.GetNonce(addr)
|
next := p.state.GetNonce(addr)
|
||||||
if uint64(len(p.index[addr])) > nonce-next {
|
if uint64(len(p.index[addr])) > nonce-next {
|
||||||
return p.index[addr][int(tx.Nonce()-next)].costCap.ToBig()
|
return p.index[addr][int(nonce-next)].costCap.ToBig()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
@ -1598,8 +1598,9 @@ func (p *BlobPool) SubscribeTransactions(ch chan<- core.NewTxsEvent, reorgs bool
|
||||||
// Nonce returns the next nonce of an account, with all transactions executable
|
// Nonce returns the next nonce of an account, with all transactions executable
|
||||||
// by the pool already applied on top.
|
// by the pool already applied on top.
|
||||||
func (p *BlobPool) Nonce(addr common.Address) uint64 {
|
func (p *BlobPool) Nonce(addr common.Address) uint64 {
|
||||||
p.lock.RLock()
|
// We need a write lock here, since state.GetNonce might write the cache.
|
||||||
defer p.lock.RUnlock()
|
p.lock.Lock()
|
||||||
|
defer p.lock.Unlock()
|
||||||
|
|
||||||
if txs, ok := p.index[addr]; ok {
|
if txs, ok := p.index[addr]; ok {
|
||||||
return txs[len(txs)-1].nonce + 1
|
return txs[len(txs)-1].nonce + 1
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -1717,7 +1718,7 @@ func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
type accountSet struct {
|
type accountSet struct {
|
||||||
accounts map[common.Address]struct{}
|
accounts map[common.Address]struct{}
|
||||||
signer types.Signer
|
signer types.Signer
|
||||||
cache *[]common.Address
|
cache []common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// newAccountSet creates a new address set with an associated signer for sender
|
// newAccountSet creates a new address set with an associated signer for sender
|
||||||
|
|
@ -1765,20 +1766,14 @@ func (as *accountSet) addTx(tx *types.Transaction) {
|
||||||
// reuse. The returned slice should not be changed!
|
// reuse. The returned slice should not be changed!
|
||||||
func (as *accountSet) flatten() []common.Address {
|
func (as *accountSet) flatten() []common.Address {
|
||||||
if as.cache == nil {
|
if as.cache == nil {
|
||||||
accounts := make([]common.Address, 0, len(as.accounts))
|
as.cache = maps.Keys(as.accounts)
|
||||||
for account := range as.accounts {
|
|
||||||
accounts = append(accounts, account)
|
|
||||||
}
|
|
||||||
as.cache = &accounts
|
|
||||||
}
|
}
|
||||||
return *as.cache
|
return as.cache
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge adds all addresses from the 'other' set into 'as'.
|
// merge adds all addresses from the 'other' set into 'as'.
|
||||||
func (as *accountSet) merge(other *accountSet) {
|
func (as *accountSet) merge(other *accountSet) {
|
||||||
for addr := range other.accounts {
|
maps.Copy(as.accounts, other.accounts)
|
||||||
as.accounts[addr] = struct{}{}
|
|
||||||
}
|
|
||||||
as.cache = nil
|
as.cache = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ type ValidationOptionsWithState struct {
|
||||||
// rules without duplicating code and running the risk of missed updates.
|
// rules without duplicating code and running the risk of missed updates.
|
||||||
func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, opts *ValidationOptionsWithState) error {
|
func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, opts *ValidationOptionsWithState) error {
|
||||||
// Ensure the transaction adheres to nonce ordering
|
// Ensure the transaction adheres to nonce ordering
|
||||||
from, err := signer.Sender(tx) // already validated (and cached), but cleaner to check
|
from, err := types.Sender(signer, tx) // already validated (and cached), but cleaner to check
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Transaction sender recovery failed", "err", err)
|
log.Error("Transaction sender recovery failed", "err", err)
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -572,6 +572,6 @@ func deriveChainId(v *big.Int) *big.Int {
|
||||||
}
|
}
|
||||||
return new(big.Int).SetUint64((v - 35) / 2)
|
return new(big.Int).SetUint64((v - 35) / 2)
|
||||||
}
|
}
|
||||||
v.Sub(v, big.NewInt(35))
|
vCopy := new(big.Int).Sub(v, big.NewInt(35))
|
||||||
return v.Rsh(v, 1)
|
return vCopy.Rsh(vCopy, 1)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -345,6 +345,41 @@ func TestTransactionCoding(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLegacyTransaction_ConsistentV_LargeChainIds(t *testing.T) {
|
||||||
|
chainId := new(big.Int).SetUint64(13317435930671861669)
|
||||||
|
|
||||||
|
txdata := &LegacyTx{
|
||||||
|
Nonce: 1,
|
||||||
|
Gas: 1,
|
||||||
|
GasPrice: big.NewInt(2),
|
||||||
|
Data: []byte("abcdef"),
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not generate key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tx, err := SignNewTx(key, NewEIP2930Signer(chainId), txdata)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not sign transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make a copy of the initial V value
|
||||||
|
preV, _, _ := tx.RawSignatureValues()
|
||||||
|
preV = new(big.Int).Set(preV)
|
||||||
|
|
||||||
|
if tx.ChainId().Cmp(chainId) != 0 {
|
||||||
|
t.Fatalf("wrong chain id: %v", tx.ChainId())
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _, _ := tx.RawSignatureValues()
|
||||||
|
|
||||||
|
if v.Cmp(preV) != 0 {
|
||||||
|
t.Fatalf("wrong v value: %v", v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func encodeDecodeJSON(tx *Transaction) (*Transaction, error) {
|
func encodeDecodeJSON(tx *Transaction) (*Transaction, error) {
|
||||||
data, err := json.Marshal(tx)
|
data, err := json.Marshal(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -583,6 +583,86 @@ func opGas(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func opSwap1(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap1()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap2(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap2()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap3(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap3()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap4(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap4()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap5(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap5()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap6(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap6()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap7(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap7()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap8(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap8()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap9(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap9()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap10(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap10()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap11(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap11()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap12(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap12()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap13(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap13()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap14(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap14()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap15(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap15()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func opSwap16(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
|
scope.Stack.swap16()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
func opCreate(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
||||||
if interpreter.readOnly {
|
if interpreter.readOnly {
|
||||||
return nil, ErrWriteProtection
|
return nil, ErrWriteProtection
|
||||||
|
|
@ -923,13 +1003,3 @@ func makeDup(size int64) executionFunc {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make swap instruction function
|
|
||||||
func makeSwap(size int64) executionFunc {
|
|
||||||
// switch n + 1 otherwise n would be swapped with n
|
|
||||||
size++
|
|
||||||
return func(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
|
|
||||||
scope.Stack.swap(int(size))
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -892,97 +892,97 @@ func newFrontierInstructionSet() JumpTable {
|
||||||
maxStack: maxDupStack(16),
|
maxStack: maxDupStack(16),
|
||||||
},
|
},
|
||||||
SWAP1: {
|
SWAP1: {
|
||||||
execute: makeSwap(1),
|
execute: opSwap1,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(2),
|
minStack: minSwapStack(2),
|
||||||
maxStack: maxSwapStack(2),
|
maxStack: maxSwapStack(2),
|
||||||
},
|
},
|
||||||
SWAP2: {
|
SWAP2: {
|
||||||
execute: makeSwap(2),
|
execute: opSwap2,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(3),
|
minStack: minSwapStack(3),
|
||||||
maxStack: maxSwapStack(3),
|
maxStack: maxSwapStack(3),
|
||||||
},
|
},
|
||||||
SWAP3: {
|
SWAP3: {
|
||||||
execute: makeSwap(3),
|
execute: opSwap3,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(4),
|
minStack: minSwapStack(4),
|
||||||
maxStack: maxSwapStack(4),
|
maxStack: maxSwapStack(4),
|
||||||
},
|
},
|
||||||
SWAP4: {
|
SWAP4: {
|
||||||
execute: makeSwap(4),
|
execute: opSwap4,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(5),
|
minStack: minSwapStack(5),
|
||||||
maxStack: maxSwapStack(5),
|
maxStack: maxSwapStack(5),
|
||||||
},
|
},
|
||||||
SWAP5: {
|
SWAP5: {
|
||||||
execute: makeSwap(5),
|
execute: opSwap5,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(6),
|
minStack: minSwapStack(6),
|
||||||
maxStack: maxSwapStack(6),
|
maxStack: maxSwapStack(6),
|
||||||
},
|
},
|
||||||
SWAP6: {
|
SWAP6: {
|
||||||
execute: makeSwap(6),
|
execute: opSwap6,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(7),
|
minStack: minSwapStack(7),
|
||||||
maxStack: maxSwapStack(7),
|
maxStack: maxSwapStack(7),
|
||||||
},
|
},
|
||||||
SWAP7: {
|
SWAP7: {
|
||||||
execute: makeSwap(7),
|
execute: opSwap7,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(8),
|
minStack: minSwapStack(8),
|
||||||
maxStack: maxSwapStack(8),
|
maxStack: maxSwapStack(8),
|
||||||
},
|
},
|
||||||
SWAP8: {
|
SWAP8: {
|
||||||
execute: makeSwap(8),
|
execute: opSwap8,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(9),
|
minStack: minSwapStack(9),
|
||||||
maxStack: maxSwapStack(9),
|
maxStack: maxSwapStack(9),
|
||||||
},
|
},
|
||||||
SWAP9: {
|
SWAP9: {
|
||||||
execute: makeSwap(9),
|
execute: opSwap9,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(10),
|
minStack: minSwapStack(10),
|
||||||
maxStack: maxSwapStack(10),
|
maxStack: maxSwapStack(10),
|
||||||
},
|
},
|
||||||
SWAP10: {
|
SWAP10: {
|
||||||
execute: makeSwap(10),
|
execute: opSwap10,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(11),
|
minStack: minSwapStack(11),
|
||||||
maxStack: maxSwapStack(11),
|
maxStack: maxSwapStack(11),
|
||||||
},
|
},
|
||||||
SWAP11: {
|
SWAP11: {
|
||||||
execute: makeSwap(11),
|
execute: opSwap11,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(12),
|
minStack: minSwapStack(12),
|
||||||
maxStack: maxSwapStack(12),
|
maxStack: maxSwapStack(12),
|
||||||
},
|
},
|
||||||
SWAP12: {
|
SWAP12: {
|
||||||
execute: makeSwap(12),
|
execute: opSwap12,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(13),
|
minStack: minSwapStack(13),
|
||||||
maxStack: maxSwapStack(13),
|
maxStack: maxSwapStack(13),
|
||||||
},
|
},
|
||||||
SWAP13: {
|
SWAP13: {
|
||||||
execute: makeSwap(13),
|
execute: opSwap13,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(14),
|
minStack: minSwapStack(14),
|
||||||
maxStack: maxSwapStack(14),
|
maxStack: maxSwapStack(14),
|
||||||
},
|
},
|
||||||
SWAP14: {
|
SWAP14: {
|
||||||
execute: makeSwap(14),
|
execute: opSwap14,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(15),
|
minStack: minSwapStack(15),
|
||||||
maxStack: maxSwapStack(15),
|
maxStack: maxSwapStack(15),
|
||||||
},
|
},
|
||||||
SWAP15: {
|
SWAP15: {
|
||||||
execute: makeSwap(15),
|
execute: opSwap15,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(16),
|
minStack: minSwapStack(16),
|
||||||
maxStack: maxSwapStack(16),
|
maxStack: maxSwapStack(16),
|
||||||
},
|
},
|
||||||
SWAP16: {
|
SWAP16: {
|
||||||
execute: makeSwap(16),
|
execute: opSwap16,
|
||||||
constantGas: GasFastestStep,
|
constantGas: GasFastestStep,
|
||||||
minStack: minSwapStack(17),
|
minStack: minSwapStack(17),
|
||||||
maxStack: maxSwapStack(17),
|
maxStack: maxSwapStack(17),
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,6 @@ import (
|
||||||
|
|
||||||
// force-load js tracers to trigger registration
|
// force-load js tracers to trigger registration
|
||||||
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||||
"github.com/holiman/uint256"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDefaults(t *testing.T) {
|
func TestDefaults(t *testing.T) {
|
||||||
|
|
@ -215,6 +214,35 @@ func BenchmarkEVM_CREATE2_1200(bench *testing.B) {
|
||||||
benchmarkEVM_Create(bench, "5b5862124f80600080f5600152600056")
|
benchmarkEVM_Create(bench, "5b5862124f80600080f5600152600056")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkEVM_SWAP1(b *testing.B) {
|
||||||
|
// returns a contract that does n swaps (SWAP1)
|
||||||
|
swapContract := func(n uint64) []byte {
|
||||||
|
contract := []byte{
|
||||||
|
byte(vm.PUSH0), // PUSH0
|
||||||
|
byte(vm.PUSH0), // PUSH0
|
||||||
|
}
|
||||||
|
for i := uint64(0); i < n; i++ {
|
||||||
|
contract = append(contract, byte(vm.SWAP1))
|
||||||
|
}
|
||||||
|
return contract
|
||||||
|
}
|
||||||
|
|
||||||
|
state, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||||
|
contractAddr := common.BytesToAddress([]byte("contract"))
|
||||||
|
|
||||||
|
b.Run("10k", func(b *testing.B) {
|
||||||
|
contractCode := swapContract(10_000)
|
||||||
|
state.SetCode(contractAddr, contractCode)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_, _, err := Call(contractAddr, []byte{}, &Config{State: state})
|
||||||
|
if err != nil {
|
||||||
|
b.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkEVM_RETURN(b *testing.B) {
|
func BenchmarkEVM_RETURN(b *testing.B) {
|
||||||
// returns a contract that returns a zero-byte slice of len size
|
// returns a contract that returns a zero-byte slice of len size
|
||||||
returnContract := func(size uint64) []byte {
|
returnContract := func(size uint64) []byte {
|
||||||
|
|
@ -376,11 +404,7 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
|
||||||
Tracer: tracer.Hooks,
|
Tracer: tracer.Hooks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var (
|
destination := common.BytesToAddress([]byte("contract"))
|
||||||
destination = common.BytesToAddress([]byte("contract"))
|
|
||||||
vmenv = NewEnv(cfg)
|
|
||||||
sender = vm.AccountRef(cfg.Origin)
|
|
||||||
)
|
|
||||||
cfg.State.CreateAccount(destination)
|
cfg.State.CreateAccount(destination)
|
||||||
eoa := common.HexToAddress("E0")
|
eoa := common.HexToAddress("E0")
|
||||||
{
|
{
|
||||||
|
|
@ -400,12 +424,12 @@ func benchmarkNonModifyingCode(gas uint64, code []byte, name string, tracerCode
|
||||||
//cfg.State.CreateAccount(cfg.Origin)
|
//cfg.State.CreateAccount(cfg.Origin)
|
||||||
// set the receiver's (the executing contract) code for execution.
|
// set the receiver's (the executing contract) code for execution.
|
||||||
cfg.State.SetCode(destination, code)
|
cfg.State.SetCode(destination, code)
|
||||||
vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value))
|
Call(destination, nil, cfg)
|
||||||
|
|
||||||
b.Run(name, func(b *testing.B) {
|
b.Run(name, func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
vmenv.Call(sender, destination, nil, gas, uint256.MustFromBig(cfg.Value))
|
Call(destination, nil, cfg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ var stackPool = sync.Pool{
|
||||||
|
|
||||||
// Stack is an object for basic stack operations. Items popped to the stack are
|
// Stack is an object for basic stack operations. Items popped to the stack are
|
||||||
// expected to be changed and modified. stack does not take care of adding newly
|
// expected to be changed and modified. stack does not take care of adding newly
|
||||||
// initialised objects.
|
// initialized objects.
|
||||||
type Stack struct {
|
type Stack struct {
|
||||||
data []uint256.Int
|
data []uint256.Int
|
||||||
}
|
}
|
||||||
|
|
@ -64,8 +64,53 @@ func (st *Stack) len() int {
|
||||||
return len(st.data)
|
return len(st.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) swap(n int) {
|
func (st *Stack) swap1() {
|
||||||
st.data[st.len()-n], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-n]
|
st.data[st.len()-2], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-2]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap2() {
|
||||||
|
st.data[st.len()-3], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-3]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap3() {
|
||||||
|
st.data[st.len()-4], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-4]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap4() {
|
||||||
|
st.data[st.len()-5], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-5]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap5() {
|
||||||
|
st.data[st.len()-6], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-6]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap6() {
|
||||||
|
st.data[st.len()-7], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-7]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap7() {
|
||||||
|
st.data[st.len()-8], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-8]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap8() {
|
||||||
|
st.data[st.len()-9], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-9]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap9() {
|
||||||
|
st.data[st.len()-10], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-10]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap10() {
|
||||||
|
st.data[st.len()-11], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-11]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap11() {
|
||||||
|
st.data[st.len()-12], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-12]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap12() {
|
||||||
|
st.data[st.len()-13], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-13]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap13() {
|
||||||
|
st.data[st.len()-14], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-14]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap14() {
|
||||||
|
st.data[st.len()-15], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-15]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap15() {
|
||||||
|
st.data[st.len()-16], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-16]
|
||||||
|
}
|
||||||
|
func (st *Stack) swap16() {
|
||||||
|
st.data[st.len()-17], st.data[st.len()-1] = st.data[st.len()-1], st.data[st.len()-17]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *Stack) dup(n int) {
|
func (st *Stack) dup(n int) {
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,7 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) {
|
||||||
return nil, errors.New("invalid private key")
|
return nil, errors.New("invalid private key")
|
||||||
}
|
}
|
||||||
defer priv.Zero()
|
defer priv.Zero()
|
||||||
sig, err := btc_ecdsa.SignCompact(&priv, hash, false) // ref uncompressed pubkey
|
sig := btc_ecdsa.SignCompact(&priv, hash, false) // ref uncompressed pubkey
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Convert to Ethereum signature format with 'recovery id' v at the end.
|
// Convert to Ethereum signature format with 'recovery id' v at the end.
|
||||||
v := sig[0] - 27
|
v := sig[0] - 27
|
||||||
copy(sig, sig[1:])
|
copy(sig, sig[1:])
|
||||||
|
|
|
||||||
|
|
@ -264,11 +264,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
if eth.APIBackend.allowUnprotectedTxs {
|
if eth.APIBackend.allowUnprotectedTxs {
|
||||||
log.Info("Unprotected transactions allowed")
|
log.Info("Unprotected transactions allowed")
|
||||||
}
|
}
|
||||||
gpoParams := config.GPO
|
eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, config.GPO, config.Miner.GasPrice)
|
||||||
if gpoParams.Default == nil {
|
|
||||||
gpoParams.Default = config.Miner.GasPrice
|
|
||||||
}
|
|
||||||
eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams)
|
|
||||||
|
|
||||||
// Setup DNS discovery iterators.
|
// Setup DNS discovery iterators.
|
||||||
dnsclient := dnsdisc.NewClient(dnsdisc.Config{})
|
dnsclient := dnsdisc.NewClient(dnsdisc.Config{})
|
||||||
|
|
|
||||||
|
|
@ -546,7 +546,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
|
||||||
bgu = strconv.Itoa(int(*params.BlobGasUsed))
|
bgu = strconv.Itoa(int(*params.BlobGasUsed))
|
||||||
}
|
}
|
||||||
ebg := "nil"
|
ebg := "nil"
|
||||||
if params.BlobGasUsed != nil {
|
if params.ExcessBlobGas != nil {
|
||||||
ebg = strconv.Itoa(int(*params.ExcessBlobGas))
|
ebg = strconv.Itoa(int(*params.ExcessBlobGas))
|
||||||
}
|
}
|
||||||
log.Warn("Invalid NewPayload params",
|
log.Warn("Invalid NewPayload params",
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,7 @@ func (c *SimulatedBeacon) AdjustTime(adjustment time.Duration) error {
|
||||||
return errors.New("parent not found")
|
return errors.New("parent not found")
|
||||||
}
|
}
|
||||||
withdrawals := c.withdrawals.gatherPending(10)
|
withdrawals := c.withdrawals.gatherPending(10)
|
||||||
return c.sealBlock(withdrawals, parent.Time+uint64(adjustment))
|
return c.sealBlock(withdrawals, parent.Time+uint64(adjustment/time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
|
func RegisterSimulatedBeaconAPIs(stack *node.Node, sim *SimulatedBeacon) {
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,8 @@ func (b *beaconBackfiller) resume() {
|
||||||
func (b *beaconBackfiller) setMode(mode SyncMode) {
|
func (b *beaconBackfiller) setMode(mode SyncMode) {
|
||||||
// Update the old sync mode and track if it was changed
|
// Update the old sync mode and track if it was changed
|
||||||
b.lock.Lock()
|
b.lock.Lock()
|
||||||
updated := b.syncMode != mode
|
oldMode := b.syncMode
|
||||||
|
updated := oldMode != mode
|
||||||
filling := b.filling
|
filling := b.filling
|
||||||
b.syncMode = mode
|
b.syncMode = mode
|
||||||
b.lock.Unlock()
|
b.lock.Unlock()
|
||||||
|
|
@ -133,7 +134,7 @@ func (b *beaconBackfiller) setMode(mode SyncMode) {
|
||||||
if !updated || !filling {
|
if !updated || !filling {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Error("Downloader sync mode changed mid-run", "old", mode.String(), "new", mode.String())
|
log.Error("Downloader sync mode changed mid-run", "old", oldMode.String(), "new", mode.String())
|
||||||
b.suspend()
|
b.suspend()
|
||||||
b.resume()
|
b.resume()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func TestFeeHistory(t *testing.T) {
|
||||||
MaxBlockHistory: c.maxBlock,
|
MaxBlockHistory: c.maxBlock,
|
||||||
}
|
}
|
||||||
backend := newTestBackend(t, big.NewInt(16), big.NewInt(28), c.pending)
|
backend := newTestBackend(t, big.NewInt(16), big.NewInt(28), c.pending)
|
||||||
oracle := NewOracle(backend, config)
|
oracle := NewOracle(backend, config, nil)
|
||||||
|
|
||||||
first, reward, baseFee, ratio, blobBaseFee, blobRatio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
|
first, reward, baseFee, ratio, blobBaseFee, blobRatio, err := oracle.FeeHistory(context.Background(), c.count, c.last, c.percent)
|
||||||
backend.teardown()
|
backend.teardown()
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ type Config struct {
|
||||||
Percentile int
|
Percentile int
|
||||||
MaxHeaderHistory uint64
|
MaxHeaderHistory uint64
|
||||||
MaxBlockHistory uint64
|
MaxBlockHistory uint64
|
||||||
Default *big.Int `toml:",omitempty"`
|
|
||||||
MaxPrice *big.Int `toml:",omitempty"`
|
MaxPrice *big.Int `toml:",omitempty"`
|
||||||
IgnorePrice *big.Int `toml:",omitempty"`
|
IgnorePrice *big.Int `toml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +78,7 @@ type Oracle struct {
|
||||||
|
|
||||||
// NewOracle returns a new gasprice oracle which can recommend suitable
|
// NewOracle returns a new gasprice oracle which can recommend suitable
|
||||||
// gasprice for newly created transaction.
|
// gasprice for newly created transaction.
|
||||||
func NewOracle(backend OracleBackend, params Config) *Oracle {
|
func NewOracle(backend OracleBackend, params Config, startPrice *big.Int) *Oracle {
|
||||||
blocks := params.Blocks
|
blocks := params.Blocks
|
||||||
if blocks < 1 {
|
if blocks < 1 {
|
||||||
blocks = 1
|
blocks = 1
|
||||||
|
|
@ -115,6 +114,9 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
||||||
maxBlockHistory = 1
|
maxBlockHistory = 1
|
||||||
log.Warn("Sanitizing invalid gasprice oracle max block history", "provided", params.MaxBlockHistory, "updated", maxBlockHistory)
|
log.Warn("Sanitizing invalid gasprice oracle max block history", "provided", params.MaxBlockHistory, "updated", maxBlockHistory)
|
||||||
}
|
}
|
||||||
|
if startPrice == nil {
|
||||||
|
startPrice = new(big.Int)
|
||||||
|
}
|
||||||
|
|
||||||
cache := lru.NewCache[cacheKey, processedFees](2048)
|
cache := lru.NewCache[cacheKey, processedFees](2048)
|
||||||
headEvent := make(chan core.ChainHeadEvent, 1)
|
headEvent := make(chan core.ChainHeadEvent, 1)
|
||||||
|
|
@ -131,7 +133,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
||||||
|
|
||||||
return &Oracle{
|
return &Oracle{
|
||||||
backend: backend,
|
backend: backend,
|
||||||
lastPrice: params.Default,
|
lastPrice: startPrice,
|
||||||
maxPrice: maxPrice,
|
maxPrice: maxPrice,
|
||||||
ignorePrice: ignorePrice,
|
ignorePrice: ignorePrice,
|
||||||
checkBlocks: blocks,
|
checkBlocks: blocks,
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,6 @@ func TestSuggestTipCap(t *testing.T) {
|
||||||
config := Config{
|
config := Config{
|
||||||
Blocks: 3,
|
Blocks: 3,
|
||||||
Percentile: 60,
|
Percentile: 60,
|
||||||
Default: big.NewInt(params.GWei),
|
|
||||||
}
|
}
|
||||||
var cases = []struct {
|
var cases = []struct {
|
||||||
fork *big.Int // London fork number
|
fork *big.Int // London fork number
|
||||||
|
|
@ -249,7 +248,7 @@ func TestSuggestTipCap(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
backend := newTestBackend(t, c.fork, nil, false)
|
backend := newTestBackend(t, c.fork, nil, false)
|
||||||
oracle := NewOracle(backend, config)
|
oracle := NewOracle(backend, config, big.NewInt(params.GWei))
|
||||||
|
|
||||||
// The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G
|
// The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G
|
||||||
got, err := oracle.SuggestTipCap(context.Background())
|
got, err := oracle.SuggestTipCap(context.Background())
|
||||||
|
|
|
||||||
|
|
@ -843,7 +843,7 @@ func TestTracingWithOverrides(t *testing.T) {
|
||||||
byte(vm.PUSH1), 00,
|
byte(vm.PUSH1), 00,
|
||||||
byte(vm.RETURN),
|
byte(vm.RETURN),
|
||||||
}),
|
}),
|
||||||
StateDiff: &map[common.Hash]common.Hash{
|
StateDiff: map[common.Hash]common.Hash{
|
||||||
common.HexToHash("0x03"): common.HexToHash("0x11"),
|
common.HexToHash("0x03"): common.HexToHash("0x11"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -898,9 +898,9 @@ func newAccounts(n int) (accounts []Account) {
|
||||||
return accounts
|
return accounts
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRPCBalance(balance *big.Int) **hexutil.Big {
|
func newRPCBalance(balance *big.Int) *hexutil.Big {
|
||||||
rpcBalance := (*hexutil.Big)(balance)
|
rpcBalance := (*hexutil.Big)(balance)
|
||||||
return &rpcBalance
|
return rpcBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRPCBytes(bytes []byte) *hexutil.Bytes {
|
func newRPCBytes(bytes []byte) *hexutil.Bytes {
|
||||||
|
|
@ -908,7 +908,7 @@ func newRPCBytes(bytes []byte) *hexutil.Bytes {
|
||||||
return &rpcBytes
|
return &rpcBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.Hash {
|
func newStates(keys []common.Hash, vals []common.Hash) map[common.Hash]common.Hash {
|
||||||
if len(keys) != len(vals) {
|
if len(keys) != len(vals) {
|
||||||
panic("invalid input")
|
panic("invalid input")
|
||||||
}
|
}
|
||||||
|
|
@ -916,7 +916,7 @@ func newStates(keys []common.Hash, vals []common.Hash) *map[common.Hash]common.H
|
||||||
for i := 0; i < len(keys); i++ {
|
for i := 0; i < len(keys); i++ {
|
||||||
m[keys[i]] = vals[i]
|
m[keys[i]] = vals[i]
|
||||||
}
|
}
|
||||||
return &m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTraceChain(t *testing.T) {
|
func TestTraceChain(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,7 @@ func (ec *Client) NetworkID(ctx context.Context) (*big.Int, error) {
|
||||||
if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil {
|
if err := ec.c.CallContext(ctx, &ver, "net_version"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, ok := version.SetString(ver, 10); !ok {
|
if _, ok := version.SetString(ver, 0); !ok {
|
||||||
return nil, fmt.Errorf("invalid net_version result %q", ver)
|
return nil, fmt.Errorf("invalid net_version result %q", ver)
|
||||||
}
|
}
|
||||||
return version, nil
|
return version, nil
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ func TestAdjustTime(t *testing.T) {
|
||||||
block2, _ := client.BlockByNumber(context.Background(), nil)
|
block2, _ := client.BlockByNumber(context.Background(), nil)
|
||||||
prevTime := block1.Time()
|
prevTime := block1.Time()
|
||||||
newTime := block2.Time()
|
newTime := block2.Time()
|
||||||
if newTime-prevTime != uint64(time.Minute) {
|
if newTime-prevTime != 60 {
|
||||||
t.Errorf("adjusted time not equal to 60 seconds. prev: %v, new: %v", prevTime, newTime)
|
t.Errorf("adjusted time not equal to 60 seconds. prev: %v, new: %v", prevTime, newTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ type KeyValueStore interface {
|
||||||
Batcher
|
Batcher
|
||||||
Iteratee
|
Iteratee
|
||||||
Compacter
|
Compacter
|
||||||
Snapshotter
|
|
||||||
io.Closer
|
io.Closer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,6 +198,5 @@ type Database interface {
|
||||||
Iteratee
|
Iteratee
|
||||||
Stater
|
Stater
|
||||||
Compacter
|
Compacter
|
||||||
Snapshotter
|
|
||||||
io.Closer
|
io.Closer
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -318,69 +318,6 @@ func TestDatabaseSuite(t *testing.T, New func() ethdb.KeyValueStore) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Snapshot", func(t *testing.T) {
|
|
||||||
db := New()
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
initial := map[string]string{
|
|
||||||
"k1": "v1", "k2": "v2", "k3": "", "k4": "",
|
|
||||||
}
|
|
||||||
for k, v := range initial {
|
|
||||||
db.Put([]byte(k), []byte(v))
|
|
||||||
}
|
|
||||||
snapshot, err := db.NewSnapshot()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for k, v := range initial {
|
|
||||||
got, err := snapshot.Get([]byte(k))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(got, []byte(v)) {
|
|
||||||
t.Fatalf("Unexpected value want: %v, got %v", v, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush more modifications into the database, ensure the snapshot
|
|
||||||
// isn't affected.
|
|
||||||
var (
|
|
||||||
update = map[string]string{"k1": "v1-b", "k3": "v3-b"}
|
|
||||||
insert = map[string]string{"k5": "v5-b"}
|
|
||||||
delete = map[string]string{"k2": ""}
|
|
||||||
)
|
|
||||||
for k, v := range update {
|
|
||||||
db.Put([]byte(k), []byte(v))
|
|
||||||
}
|
|
||||||
for k, v := range insert {
|
|
||||||
db.Put([]byte(k), []byte(v))
|
|
||||||
}
|
|
||||||
for k := range delete {
|
|
||||||
db.Delete([]byte(k))
|
|
||||||
}
|
|
||||||
for k, v := range initial {
|
|
||||||
got, err := snapshot.Get([]byte(k))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(got, []byte(v)) {
|
|
||||||
t.Fatalf("Unexpected value want: %v, got %v", v, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range insert {
|
|
||||||
got, err := snapshot.Get([]byte(k))
|
|
||||||
if err == nil || len(got) != 0 {
|
|
||||||
t.Fatal("Unexpected value")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k := range delete {
|
|
||||||
got, err := snapshot.Get([]byte(k))
|
|
||||||
if err != nil || len(got) == 0 {
|
|
||||||
t.Fatal("Unexpected deletion")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("OperationsAfterClose", func(t *testing.T) {
|
t.Run("OperationsAfterClose", func(t *testing.T) {
|
||||||
db := New()
|
db := New()
|
||||||
db.Put([]byte("key"), []byte("value"))
|
db.Put([]byte("key"), []byte("value"))
|
||||||
|
|
|
||||||
|
|
@ -230,19 +230,6 @@ func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
|
||||||
return db.db.NewIterator(bytesPrefixRange(prefix, start), nil)
|
return db.db.NewIterator(bytesPrefixRange(prefix, start), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSnapshot creates a database snapshot based on the current state.
|
|
||||||
// The created snapshot will not be affected by all following mutations
|
|
||||||
// happened on the database.
|
|
||||||
// Note don't forget to release the snapshot once it's used up, otherwise
|
|
||||||
// the stale data will never be cleaned up by the underlying compactor.
|
|
||||||
func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
|
|
||||||
snap, err := db.db.GetSnapshot()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &snapshot{db: snap}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stat returns the statistic data of the database.
|
// Stat returns the statistic data of the database.
|
||||||
func (db *Database) Stat() (string, error) {
|
func (db *Database) Stat() (string, error) {
|
||||||
var stats leveldb.DBStats
|
var stats leveldb.DBStats
|
||||||
|
|
@ -498,26 +485,3 @@ func bytesPrefixRange(prefix, start []byte) *util.Range {
|
||||||
r.Start = append(r.Start, start...)
|
r.Start = append(r.Start, start...)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// snapshot wraps a leveldb snapshot for implementing the Snapshot interface.
|
|
||||||
type snapshot struct {
|
|
||||||
db *leveldb.Snapshot
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has retrieves if a key is present in the snapshot backing by a key-value
|
|
||||||
// data store.
|
|
||||||
func (snap *snapshot) Has(key []byte) (bool, error) {
|
|
||||||
return snap.db.Has(key, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves the given key if it's present in the snapshot backing by
|
|
||||||
// key-value data store.
|
|
||||||
func (snap *snapshot) Get(key []byte) ([]byte, error) {
|
|
||||||
return snap.db.Get(key, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release releases associated resources. Release should always succeed and can
|
|
||||||
// be called multiple times without causing error.
|
|
||||||
func (snap *snapshot) Release() {
|
|
||||||
snap.db.Release()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,6 @@ var (
|
||||||
// errMemorydbNotFound is returned if a key is requested that is not found in
|
// errMemorydbNotFound is returned if a key is requested that is not found in
|
||||||
// the provided memory database.
|
// the provided memory database.
|
||||||
errMemorydbNotFound = errors.New("not found")
|
errMemorydbNotFound = errors.New("not found")
|
||||||
|
|
||||||
// errSnapshotReleased is returned if callers want to retrieve data from a
|
|
||||||
// released snapshot.
|
|
||||||
errSnapshotReleased = errors.New("snapshot released")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Database is an ephemeral key-value store. Apart from basic data storage
|
// Database is an ephemeral key-value store. Apart from basic data storage
|
||||||
|
|
@ -175,13 +171,6 @@ func (db *Database) NewIterator(prefix []byte, start []byte) ethdb.Iterator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSnapshot creates a database snapshot based on the current state.
|
|
||||||
// The created snapshot will not be affected by all following mutations
|
|
||||||
// happened on the database.
|
|
||||||
func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
|
|
||||||
return newSnapshot(db), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stat returns the statistic data of the database.
|
// Stat returns the statistic data of the database.
|
||||||
func (db *Database) Stat() (string, error) {
|
func (db *Database) Stat() (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
|
|
@ -332,59 +321,3 @@ func (it *iterator) Value() []byte {
|
||||||
func (it *iterator) Release() {
|
func (it *iterator) Release() {
|
||||||
it.index, it.keys, it.values = -1, nil, nil
|
it.index, it.keys, it.values = -1, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// snapshot wraps a batch of key-value entries deep copied from the in-memory
|
|
||||||
// database for implementing the Snapshot interface.
|
|
||||||
type snapshot struct {
|
|
||||||
db map[string][]byte
|
|
||||||
lock sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// newSnapshot initializes the snapshot with the given database instance.
|
|
||||||
func newSnapshot(db *Database) *snapshot {
|
|
||||||
db.lock.RLock()
|
|
||||||
defer db.lock.RUnlock()
|
|
||||||
|
|
||||||
copied := make(map[string][]byte, len(db.db))
|
|
||||||
for key, val := range db.db {
|
|
||||||
copied[key] = common.CopyBytes(val)
|
|
||||||
}
|
|
||||||
return &snapshot{db: copied}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has retrieves if a key is present in the snapshot backing by a key-value
|
|
||||||
// data store.
|
|
||||||
func (snap *snapshot) Has(key []byte) (bool, error) {
|
|
||||||
snap.lock.RLock()
|
|
||||||
defer snap.lock.RUnlock()
|
|
||||||
|
|
||||||
if snap.db == nil {
|
|
||||||
return false, errSnapshotReleased
|
|
||||||
}
|
|
||||||
_, ok := snap.db[string(key)]
|
|
||||||
return ok, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves the given key if it's present in the snapshot backing by
|
|
||||||
// key-value data store.
|
|
||||||
func (snap *snapshot) Get(key []byte) ([]byte, error) {
|
|
||||||
snap.lock.RLock()
|
|
||||||
defer snap.lock.RUnlock()
|
|
||||||
|
|
||||||
if snap.db == nil {
|
|
||||||
return nil, errSnapshotReleased
|
|
||||||
}
|
|
||||||
if entry, ok := snap.db[string(key)]; ok {
|
|
||||||
return common.CopyBytes(entry), nil
|
|
||||||
}
|
|
||||||
return nil, errMemorydbNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release releases associated resources. Release should always succeed and can
|
|
||||||
// be called multiple times without causing error.
|
|
||||||
func (snap *snapshot) Release() {
|
|
||||||
snap.lock.Lock()
|
|
||||||
defer snap.lock.Unlock()
|
|
||||||
|
|
||||||
snap.db = nil
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -351,55 +351,6 @@ func (d *Database) NewBatchWithSize(size int) ethdb.Batch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// snapshot wraps a pebble snapshot for implementing the Snapshot interface.
|
|
||||||
type snapshot struct {
|
|
||||||
db *pebble.Snapshot
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSnapshot creates a database snapshot based on the current state.
|
|
||||||
// The created snapshot will not be affected by all following mutations
|
|
||||||
// happened on the database.
|
|
||||||
// Note don't forget to release the snapshot once it's used up, otherwise
|
|
||||||
// the stale data will never be cleaned up by the underlying compactor.
|
|
||||||
func (d *Database) NewSnapshot() (ethdb.Snapshot, error) {
|
|
||||||
snap := d.db.NewSnapshot()
|
|
||||||
return &snapshot{db: snap}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has retrieves if a key is present in the snapshot backing by a key-value
|
|
||||||
// data store.
|
|
||||||
func (snap *snapshot) Has(key []byte) (bool, error) {
|
|
||||||
_, closer, err := snap.db.Get(key)
|
|
||||||
if err != nil {
|
|
||||||
if err != pebble.ErrNotFound {
|
|
||||||
return false, err
|
|
||||||
} else {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closer.Close()
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get retrieves the given key if it's present in the snapshot backing by
|
|
||||||
// key-value data store.
|
|
||||||
func (snap *snapshot) Get(key []byte) ([]byte, error) {
|
|
||||||
dat, closer, err := snap.db.Get(key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret := make([]byte, len(dat))
|
|
||||||
copy(ret, dat)
|
|
||||||
closer.Close()
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release releases associated resources. Release should always succeed and can
|
|
||||||
// be called multiple times without causing error.
|
|
||||||
func (snap *snapshot) Release() {
|
|
||||||
snap.db.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// upperBound returns the upper bound for the given prefix
|
// upperBound returns the upper bound for the given prefix
|
||||||
func upperBound(prefix []byte) (limit []byte) {
|
func upperBound(prefix []byte) (limit []byte) {
|
||||||
for i := len(prefix) - 1; i >= 0; i-- {
|
for i := len(prefix) - 1; i >= 0; i-- {
|
||||||
|
|
|
||||||
|
|
@ -138,10 +138,6 @@ func (db *Database) Compact(start []byte, limit []byte) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *Database) NewSnapshot() (ethdb.Snapshot, error) {
|
|
||||||
panic("not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *Database) Close() error {
|
func (db *Database) Close() error {
|
||||||
db.remote.Close()
|
db.remote.Close()
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2022 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package ethdb
|
|
||||||
|
|
||||||
type Snapshot interface {
|
|
||||||
// Has retrieves if a key is present in the snapshot backing by a key-value
|
|
||||||
// data store.
|
|
||||||
Has(key []byte) (bool, error)
|
|
||||||
|
|
||||||
// Get retrieves the given key if it's present in the snapshot backing by
|
|
||||||
// key-value data store.
|
|
||||||
Get(key []byte) ([]byte, error)
|
|
||||||
|
|
||||||
// Release releases associated resources. Release should always succeed and can
|
|
||||||
// be called multiple times without causing error.
|
|
||||||
Release()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Snapshotter wraps the Snapshot method of a backing data store.
|
|
||||||
type Snapshotter interface {
|
|
||||||
// NewSnapshot creates a database snapshot based on the current state.
|
|
||||||
// The created snapshot will not be affected by all following mutations
|
|
||||||
// happened on the database.
|
|
||||||
// Note don't forget to release the snapshot once it's used up, otherwise
|
|
||||||
// the stale data will never be cleaned up by the underlying compactor.
|
|
||||||
NewSnapshot() (Snapshot, error)
|
|
||||||
}
|
|
||||||
7
go.mod
7
go.mod
|
|
@ -10,7 +10,7 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.18.45
|
github.com/aws/aws-sdk-go-v2/config v1.18.45
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.13.43
|
github.com/aws/aws-sdk-go-v2/credentials v1.13.43
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0
|
github.com/btcsuite/btcd/btcec/v2 v2.3.4
|
||||||
github.com/cespare/cp v0.1.0
|
github.com/cespare/cp v0.1.0
|
||||||
github.com/cloudflare/cloudflare-go v0.79.0
|
github.com/cloudflare/cloudflare-go v0.79.0
|
||||||
github.com/cockroachdb/pebble v1.1.1
|
github.com/cockroachdb/pebble v1.1.1
|
||||||
|
|
@ -26,12 +26,10 @@ require (
|
||||||
github.com/fatih/color v1.16.0
|
github.com/fatih/color v1.16.0
|
||||||
github.com/ferranbt/fastssz v0.1.2
|
github.com/ferranbt/fastssz v0.1.2
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e
|
||||||
github.com/fjl/memsize v0.0.2
|
|
||||||
github.com/fsnotify/fsnotify v1.6.0
|
github.com/fsnotify/fsnotify v1.6.0
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
|
||||||
github.com/gofrs/flock v0.8.1
|
github.com/gofrs/flock v0.8.1
|
||||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||||
github.com/golang/protobuf v1.5.4
|
|
||||||
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
|
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb
|
||||||
github.com/google/gofuzz v1.2.0
|
github.com/google/gofuzz v1.2.0
|
||||||
github.com/google/uuid v1.3.0
|
github.com/google/uuid v1.3.0
|
||||||
|
|
@ -74,7 +72,7 @@ require (
|
||||||
golang.org/x/text v0.14.0
|
golang.org/x/text v0.14.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.5.0
|
||||||
golang.org/x/tools v0.20.0
|
golang.org/x/tools v0.20.0
|
||||||
google.golang.org/protobuf v1.33.0
|
google.golang.org/protobuf v1.34.2
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
@ -112,6 +110,7 @@ require (
|
||||||
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
|
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
|
|
|
||||||
8
go.sum
8
go.sum
|
|
@ -92,8 +92,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
|
github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88=
|
||||||
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k=
|
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU=
|
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
|
||||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
|
@ -178,8 +178,6 @@ github.com/ferranbt/fastssz v0.1.2 h1:Dky6dXlngF6Qjc+EfDipAkE83N5I5DE68bY6O0VLNP
|
||||||
github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs=
|
github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs=
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY=
|
||||||
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
|
github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY=
|
||||||
github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA=
|
|
||||||
github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
|
|
@ -842,6 +840,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,12 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/metrics/exp"
|
"github.com/ethereum/go-ethereum/metrics/exp"
|
||||||
"github.com/fjl/memsize/memsizeui"
|
|
||||||
"github.com/mattn/go-colorable"
|
"github.com/mattn/go-colorable"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Memsize memsizeui.Handler
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
verbosityFlag = &cli.IntFlag{
|
verbosityFlag = &cli.IntFlag{
|
||||||
Name: "verbosity",
|
Name: "verbosity",
|
||||||
|
|
@ -313,7 +310,6 @@ func StartPProf(address string, withMetrics bool) {
|
||||||
if withMetrics {
|
if withMetrics {
|
||||||
exp.Exp(metrics.DefaultRegistry)
|
exp.Exp(metrics.DefaultRegistry)
|
||||||
}
|
}
|
||||||
http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize))
|
|
||||||
log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address))
|
log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address))
|
||||||
go func() {
|
go func() {
|
||||||
if err := http.ListenAndServe(address, nil); err != nil {
|
if err := http.ListenAndServe(address, nil); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -968,11 +968,11 @@ func (api *BlockChainAPI) GetBlockReceipts(ctx context.Context, blockNrOrHash rp
|
||||||
// if stateDiff is set, all diff will be applied first and then execute the call
|
// if stateDiff is set, all diff will be applied first and then execute the call
|
||||||
// message.
|
// message.
|
||||||
type OverrideAccount struct {
|
type OverrideAccount struct {
|
||||||
Nonce *hexutil.Uint64 `json:"nonce"`
|
Nonce *hexutil.Uint64 `json:"nonce"`
|
||||||
Code *hexutil.Bytes `json:"code"`
|
Code *hexutil.Bytes `json:"code"`
|
||||||
Balance **hexutil.Big `json:"balance"`
|
Balance *hexutil.Big `json:"balance"`
|
||||||
State *map[common.Hash]common.Hash `json:"state"`
|
State map[common.Hash]common.Hash `json:"state"`
|
||||||
StateDiff *map[common.Hash]common.Hash `json:"stateDiff"`
|
StateDiff map[common.Hash]common.Hash `json:"stateDiff"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateOverride is the collection of overridden accounts.
|
// StateOverride is the collection of overridden accounts.
|
||||||
|
|
@ -994,7 +994,7 @@ func (diff *StateOverride) Apply(statedb *state.StateDB) error {
|
||||||
}
|
}
|
||||||
// Override account balance.
|
// Override account balance.
|
||||||
if account.Balance != nil {
|
if account.Balance != nil {
|
||||||
u256Balance, _ := uint256.FromBig((*big.Int)(*account.Balance))
|
u256Balance, _ := uint256.FromBig((*big.Int)(account.Balance))
|
||||||
statedb.SetBalance(addr, u256Balance, tracing.BalanceChangeUnspecified)
|
statedb.SetBalance(addr, u256Balance, tracing.BalanceChangeUnspecified)
|
||||||
}
|
}
|
||||||
if account.State != nil && account.StateDiff != nil {
|
if account.State != nil && account.StateDiff != nil {
|
||||||
|
|
@ -1002,11 +1002,11 @@ func (diff *StateOverride) Apply(statedb *state.StateDB) error {
|
||||||
}
|
}
|
||||||
// Replace entire state if caller requires.
|
// Replace entire state if caller requires.
|
||||||
if account.State != nil {
|
if account.State != nil {
|
||||||
statedb.SetStorage(addr, *account.State)
|
statedb.SetStorage(addr, account.State)
|
||||||
}
|
}
|
||||||
// Apply state diff into specified accounts.
|
// Apply state diff into specified accounts.
|
||||||
if account.StateDiff != nil {
|
if account.StateDiff != nil {
|
||||||
for key, value := range *account.StateDiff {
|
for key, value := range account.StateDiff {
|
||||||
statedb.SetState(addr, key, value)
|
statedb.SetState(addr, key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -781,15 +781,24 @@ func TestEstimateGas(t *testing.T) {
|
||||||
|
|
||||||
func TestCall(t *testing.T) {
|
func TestCall(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
// Initialize test accounts
|
// Initialize test accounts
|
||||||
var (
|
var (
|
||||||
accounts = newAccounts(3)
|
accounts = newAccounts(3)
|
||||||
|
dad = common.HexToAddress("0x0000000000000000000000000000000000000dad")
|
||||||
genesis = &core.Genesis{
|
genesis = &core.Genesis{
|
||||||
Config: params.MergedTestChainConfig,
|
Config: params.MergedTestChainConfig,
|
||||||
Alloc: types.GenesisAlloc{
|
Alloc: types.GenesisAlloc{
|
||||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||||
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
||||||
|
dad: {
|
||||||
|
Balance: big.NewInt(params.Ether),
|
||||||
|
Nonce: 1,
|
||||||
|
Storage: map[common.Hash]common.Hash{
|
||||||
|
common.Hash{}: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001"),
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
genBlocks = 10
|
genBlocks = 10
|
||||||
|
|
@ -904,7 +913,7 @@ func TestCall(t *testing.T) {
|
||||||
overrides: StateOverride{
|
overrides: StateOverride{
|
||||||
randomAccounts[2].addr: OverrideAccount{
|
randomAccounts[2].addr: OverrideAccount{
|
||||||
Code: hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033"),
|
Code: hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033"),
|
||||||
StateDiff: &map[common.Hash]common.Hash{{}: common.BigToHash(big.NewInt(123))},
|
StateDiff: map[common.Hash]common.Hash{{}: common.BigToHash(big.NewInt(123))},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
want: "0x000000000000000000000000000000000000000000000000000000000000007b",
|
want: "0x000000000000000000000000000000000000000000000000000000000000007b",
|
||||||
|
|
@ -949,6 +958,32 @@ func TestCall(t *testing.T) {
|
||||||
},
|
},
|
||||||
want: "0x0122000000000000000000000000000000000000000000000000000000000000",
|
want: "0x0122000000000000000000000000000000000000000000000000000000000000",
|
||||||
},
|
},
|
||||||
|
// Clear the entire storage set
|
||||||
|
{
|
||||||
|
blockNumber: rpc.LatestBlockNumber,
|
||||||
|
call: TransactionArgs{
|
||||||
|
From: &accounts[1].addr,
|
||||||
|
// Yul:
|
||||||
|
// object "Test" {
|
||||||
|
// code {
|
||||||
|
// let dad := 0x0000000000000000000000000000000000000dad
|
||||||
|
// if eq(balance(dad), 0) {
|
||||||
|
// revert(0, 0)
|
||||||
|
// }
|
||||||
|
// let slot := sload(0)
|
||||||
|
// mstore(0, slot)
|
||||||
|
// return(0, 32)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
Input: hex2Bytes("610dad6000813103600f57600080fd5b6000548060005260206000f3"),
|
||||||
|
},
|
||||||
|
overrides: StateOverride{
|
||||||
|
dad: OverrideAccount{
|
||||||
|
State: map[common.Hash]common.Hash{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for i, tc := range testSuite {
|
for i, tc := range testSuite {
|
||||||
result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
|
result, err := api.Call(context.Background(), tc.call, &rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, &tc.overrides, &tc.blockOverrides)
|
||||||
|
|
@ -1308,9 +1343,9 @@ func newAccounts(n int) (accounts []account) {
|
||||||
return accounts
|
return accounts
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRPCBalance(balance *big.Int) **hexutil.Big {
|
func newRPCBalance(balance *big.Int) *hexutil.Big {
|
||||||
rpcBalance := (*hexutil.Big)(balance)
|
rpcBalance := (*hexutil.Big)(balance)
|
||||||
return &rpcBalance
|
return rpcBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
func hex2Bytes(str string) *hexutil.Bytes {
|
func hex2Bytes(str string) *hexutil.Bytes {
|
||||||
|
|
|
||||||
|
|
@ -205,8 +205,7 @@ func (miner *Miner) prepareWork(genParams *generateParams) (*environment, error)
|
||||||
|
|
||||||
// makeEnv creates a new environment for the sealing block.
|
// makeEnv creates a new environment for the sealing block.
|
||||||
func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address) (*environment, error) {
|
func (miner *Miner) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address) (*environment, error) {
|
||||||
// Retrieve the parent state to execute on top and start a prefetcher for
|
// Retrieve the parent state to execute on top.
|
||||||
// the miner to speed block sealing up a bit.
|
|
||||||
state, err := miner.chain.StateAt(parent.Root)
|
state, err := miner.chain.StateAt(parent.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,10 @@
|
||||||
package discover
|
package discover
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -48,33 +42,6 @@ type tableNode struct {
|
||||||
isValidatedLive bool // true if existence of node is considered validated right now
|
isValidatedLive bool // true if existence of node is considered validated right now
|
||||||
}
|
}
|
||||||
|
|
||||||
type encPubkey [64]byte
|
|
||||||
|
|
||||||
func encodePubkey(key *ecdsa.PublicKey) encPubkey {
|
|
||||||
var e encPubkey
|
|
||||||
math.ReadBits(key.X, e[:len(e)/2])
|
|
||||||
math.ReadBits(key.Y, e[len(e)/2:])
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodePubkey(curve elliptic.Curve, e []byte) (*ecdsa.PublicKey, error) {
|
|
||||||
if len(e) != len(encPubkey{}) {
|
|
||||||
return nil, errors.New("wrong size public key data")
|
|
||||||
}
|
|
||||||
p := &ecdsa.PublicKey{Curve: curve, X: new(big.Int), Y: new(big.Int)}
|
|
||||||
half := len(e) / 2
|
|
||||||
p.X.SetBytes(e[:half])
|
|
||||||
p.Y.SetBytes(e[half:])
|
|
||||||
if !p.Curve.IsOnCurve(p.X, p.Y) {
|
|
||||||
return nil, errors.New("invalid curve point")
|
|
||||||
}
|
|
||||||
return p, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e encPubkey) id() enode.ID {
|
|
||||||
return enode.ID(crypto.Keccak256Hash(e[:]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func unwrapNodes(ns []*tableNode) []*enode.Node {
|
func unwrapNodes(ns []*tableNode) []*enode.Node {
|
||||||
result := make([]*enode.Node, len(ns))
|
result := make([]*enode.Node, len(ns))
|
||||||
for i, n := range ns {
|
for i, n := range ns {
|
||||||
|
|
|
||||||
|
|
@ -77,14 +77,18 @@ func (tr *tableRevalidation) nodeEndpointChanged(tab *Table, n *tableNode) {
|
||||||
// It returns the next time it should be invoked, which is used in the Table main loop
|
// It returns the next time it should be invoked, which is used in the Table main loop
|
||||||
// to schedule a timer. However, run can be called at any time.
|
// to schedule a timer. However, run can be called at any time.
|
||||||
func (tr *tableRevalidation) run(tab *Table, now mclock.AbsTime) (nextTime mclock.AbsTime) {
|
func (tr *tableRevalidation) run(tab *Table, now mclock.AbsTime) (nextTime mclock.AbsTime) {
|
||||||
if n := tr.fast.get(now, &tab.rand, tr.activeReq); n != nil {
|
reval := func(list *revalidationList) {
|
||||||
tr.startRequest(tab, n)
|
if list.nextTime <= now {
|
||||||
tr.fast.schedule(now, &tab.rand)
|
if n := list.get(now, &tab.rand, tr.activeReq); n != nil {
|
||||||
}
|
tr.startRequest(tab, n)
|
||||||
if n := tr.slow.get(now, &tab.rand, tr.activeReq); n != nil {
|
}
|
||||||
tr.startRequest(tab, n)
|
// Update nextTime regardless if any requests were started because
|
||||||
tr.slow.schedule(now, &tab.rand)
|
// current value has passed.
|
||||||
|
list.schedule(now, &tab.rand)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
reval(&tr.fast)
|
||||||
|
reval(&tr.slow)
|
||||||
|
|
||||||
return min(tr.fast.nextTime, tr.slow.nextTime)
|
return min(tr.fast.nextTime, tr.slow.nextTime)
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +204,7 @@ type revalidationList struct {
|
||||||
|
|
||||||
// get returns a random node from the queue. Nodes in the 'exclude' map are not returned.
|
// get returns a random node from the queue. Nodes in the 'exclude' map are not returned.
|
||||||
func (list *revalidationList) get(now mclock.AbsTime, rand randomSource, exclude map[enode.ID]struct{}) *tableNode {
|
func (list *revalidationList) get(now mclock.AbsTime, rand randomSource, exclude map[enode.ID]struct{}) *tableNode {
|
||||||
if now < list.nextTime || len(list.nodes) == 0 {
|
if len(list.nodes) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for i := 0; i < len(list.nodes)*3; i++ {
|
for i := 0; i < len(list.nodes)*3; i++ {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/discover/v4wire"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
)
|
)
|
||||||
|
|
@ -284,7 +285,7 @@ func hexEncPrivkey(h string) *ecdsa.PrivateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// hexEncPubkey decodes h as a public key.
|
// hexEncPubkey decodes h as a public key.
|
||||||
func hexEncPubkey(h string) (ret encPubkey) {
|
func hexEncPubkey(h string) (ret v4wire.Pubkey) {
|
||||||
b, err := hex.DecodeString(h)
|
b, err := hex.DecodeString(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func TestUDPv4_Lookup(t *testing.T) {
|
||||||
test := newUDPTest(t)
|
test := newUDPTest(t)
|
||||||
|
|
||||||
// Lookup on empty table returns no nodes.
|
// Lookup on empty table returns no nodes.
|
||||||
targetKey, _ := decodePubkey(crypto.S256(), lookupTestnet.target[:])
|
targetKey, _ := v4wire.DecodePubkey(crypto.S256(), lookupTestnet.target)
|
||||||
if results := test.udp.LookupPubkey(targetKey); len(results) > 0 {
|
if results := test.udp.LookupPubkey(targetKey); len(results) > 0 {
|
||||||
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
|
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +56,7 @@ func TestUDPv4_Lookup(t *testing.T) {
|
||||||
results := <-resultC
|
results := <-resultC
|
||||||
t.Logf("results:")
|
t.Logf("results:")
|
||||||
for _, e := range results {
|
for _, e := range results {
|
||||||
t.Logf(" ld=%d, %x", enode.LogDist(lookupTestnet.target.id(), e.ID()), e.ID().Bytes())
|
t.Logf(" ld=%d, %x", enode.LogDist(lookupTestnet.target.ID(), e.ID()), e.ID().Bytes())
|
||||||
}
|
}
|
||||||
if len(results) != bucketSize {
|
if len(results) != bucketSize {
|
||||||
t.Errorf("wrong number of results: got %d, want %d", len(results), bucketSize)
|
t.Errorf("wrong number of results: got %d, want %d", len(results), bucketSize)
|
||||||
|
|
@ -142,7 +142,7 @@ func serveTestnet(test *udpTest, testnet *preminedTestnet) {
|
||||||
case *v4wire.Ping:
|
case *v4wire.Ping:
|
||||||
test.packetInFrom(nil, key, to, &v4wire.Pong{Expiration: futureExp, ReplyTok: hash})
|
test.packetInFrom(nil, key, to, &v4wire.Pong{Expiration: futureExp, ReplyTok: hash})
|
||||||
case *v4wire.Findnode:
|
case *v4wire.Findnode:
|
||||||
dist := enode.LogDist(n.ID(), testnet.target.id())
|
dist := enode.LogDist(n.ID(), testnet.target.ID())
|
||||||
nodes := testnet.nodesAtDistance(dist - 1)
|
nodes := testnet.nodesAtDistance(dist - 1)
|
||||||
test.packetInFrom(nil, key, to, &v4wire.Neighbors{Expiration: futureExp, Nodes: nodes})
|
test.packetInFrom(nil, key, to, &v4wire.Neighbors{Expiration: futureExp, Nodes: nodes})
|
||||||
}
|
}
|
||||||
|
|
@ -156,12 +156,12 @@ func checkLookupResults(t *testing.T, tn *preminedTestnet, results []*enode.Node
|
||||||
t.Helper()
|
t.Helper()
|
||||||
t.Logf("results:")
|
t.Logf("results:")
|
||||||
for _, e := range results {
|
for _, e := range results {
|
||||||
t.Logf(" ld=%d, %x", enode.LogDist(tn.target.id(), e.ID()), e.ID().Bytes())
|
t.Logf(" ld=%d, %x", enode.LogDist(tn.target.ID(), e.ID()), e.ID().Bytes())
|
||||||
}
|
}
|
||||||
if hasDuplicates(results) {
|
if hasDuplicates(results) {
|
||||||
t.Errorf("result set contains duplicate entries")
|
t.Errorf("result set contains duplicate entries")
|
||||||
}
|
}
|
||||||
if !sortedByDistanceTo(tn.target.id(), results) {
|
if !sortedByDistanceTo(tn.target.ID(), results) {
|
||||||
t.Errorf("result set not sorted by distance to target")
|
t.Errorf("result set not sorted by distance to target")
|
||||||
}
|
}
|
||||||
wantNodes := tn.closest(len(results))
|
wantNodes := tn.closest(len(results))
|
||||||
|
|
@ -231,7 +231,7 @@ var lookupTestnet = &preminedTestnet{
|
||||||
}
|
}
|
||||||
|
|
||||||
type preminedTestnet struct {
|
type preminedTestnet struct {
|
||||||
target encPubkey
|
target v4wire.Pubkey
|
||||||
dists [hashBits + 1][]*ecdsa.PrivateKey
|
dists [hashBits + 1][]*ecdsa.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,7 +304,7 @@ func (tn *preminedTestnet) closest(n int) (nodes []*enode.Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slices.SortFunc(nodes, func(a, b *enode.Node) int {
|
slices.SortFunc(nodes, func(a, b *enode.Node) int {
|
||||||
return enode.DistCmp(tn.target.id(), a.ID(), b.ID())
|
return enode.DistCmp(tn.target.ID(), a.ID(), b.ID())
|
||||||
})
|
})
|
||||||
return nodes[:n]
|
return nodes[:n]
|
||||||
}
|
}
|
||||||
|
|
@ -319,11 +319,11 @@ func (tn *preminedTestnet) mine() {
|
||||||
tn.dists[i] = nil
|
tn.dists[i] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
targetSha := tn.target.id()
|
targetSha := tn.target.ID()
|
||||||
found, need := 0, 40
|
found, need := 0, 40
|
||||||
for found < need {
|
for found < need {
|
||||||
k := newkey()
|
k := newkey()
|
||||||
ld := enode.LogDist(targetSha, encodePubkey(&k.PublicKey).id())
|
ld := enode.LogDist(targetSha, v4wire.EncodePubkey(&k.PublicKey).ID())
|
||||||
if len(tn.dists[ld]) < 8 {
|
if len(tn.dists[ld]) < 8 {
|
||||||
tn.dists[ld] = append(tn.dists[ld], k)
|
tn.dists[ld] = append(tn.dists[ld], k)
|
||||||
found++
|
found++
|
||||||
|
|
|
||||||
|
|
@ -271,7 +271,7 @@ func (t *UDPv4) LookupPubkey(key *ecdsa.PublicKey) []*enode.Node {
|
||||||
// case and run the bootstrapping logic.
|
// case and run the bootstrapping logic.
|
||||||
<-t.tab.refresh()
|
<-t.tab.refresh()
|
||||||
}
|
}
|
||||||
return t.newLookup(t.closeCtx, encodePubkey(key)).run()
|
return t.newLookup(t.closeCtx, v4wire.EncodePubkey(key)).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// RandomNodes is an iterator yielding nodes from a random walk of the DHT.
|
// RandomNodes is an iterator yielding nodes from a random walk of the DHT.
|
||||||
|
|
@ -286,24 +286,24 @@ func (t *UDPv4) lookupRandom() []*enode.Node {
|
||||||
|
|
||||||
// lookupSelf implements transport.
|
// lookupSelf implements transport.
|
||||||
func (t *UDPv4) lookupSelf() []*enode.Node {
|
func (t *UDPv4) lookupSelf() []*enode.Node {
|
||||||
return t.newLookup(t.closeCtx, encodePubkey(&t.priv.PublicKey)).run()
|
pubkey := v4wire.EncodePubkey(&t.priv.PublicKey)
|
||||||
|
return t.newLookup(t.closeCtx, pubkey).run()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) newRandomLookup(ctx context.Context) *lookup {
|
func (t *UDPv4) newRandomLookup(ctx context.Context) *lookup {
|
||||||
var target encPubkey
|
var target v4wire.Pubkey
|
||||||
crand.Read(target[:])
|
crand.Read(target[:])
|
||||||
return t.newLookup(ctx, target)
|
return t.newLookup(ctx, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *UDPv4) newLookup(ctx context.Context, targetKey encPubkey) *lookup {
|
func (t *UDPv4) newLookup(ctx context.Context, targetKey v4wire.Pubkey) *lookup {
|
||||||
target := enode.ID(crypto.Keccak256Hash(targetKey[:]))
|
target := enode.ID(crypto.Keccak256Hash(targetKey[:]))
|
||||||
ekey := v4wire.Pubkey(targetKey)
|
|
||||||
it := newLookup(ctx, t.tab, target, func(n *enode.Node) ([]*enode.Node, error) {
|
it := newLookup(ctx, t.tab, target, func(n *enode.Node) ([]*enode.Node, error) {
|
||||||
addr, ok := n.UDPEndpoint()
|
addr, ok := n.UDPEndpoint()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errNoUDPEndpoint
|
return nil, errNoUDPEndpoint
|
||||||
}
|
}
|
||||||
return t.findnode(n.ID(), addr, ekey)
|
return t.findnode(n.ID(), addr, targetKey)
|
||||||
})
|
})
|
||||||
return it
|
return it
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ func TestUDPv4_findnodeMultiReply(t *testing.T) {
|
||||||
// queue a pending findnode request
|
// queue a pending findnode request
|
||||||
resultc, errc := make(chan []*enode.Node, 1), make(chan error, 1)
|
resultc, errc := make(chan []*enode.Node, 1), make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
rid := encodePubkey(&test.remotekey.PublicKey).id()
|
rid := v4wire.EncodePubkey(&test.remotekey.PublicKey).ID()
|
||||||
ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget)
|
ns, err := test.udp.findnode(rid, test.remoteaddr, testTarget)
|
||||||
if err != nil && len(ns) == 0 {
|
if err != nil && len(ns) == 0 {
|
||||||
errc <- err
|
errc <- err
|
||||||
|
|
@ -433,7 +433,7 @@ func TestUDPv4_successfulPing(t *testing.T) {
|
||||||
// pong packet.
|
// pong packet.
|
||||||
select {
|
select {
|
||||||
case n := <-added:
|
case n := <-added:
|
||||||
rid := encodePubkey(&test.remotekey.PublicKey).id()
|
rid := v4wire.EncodePubkey(&test.remotekey.PublicKey).ID()
|
||||||
if n.ID() != rid {
|
if n.ID() != rid {
|
||||||
t.Errorf("node has wrong ID: got %v, want %v", n.ID(), rid)
|
t.Errorf("node has wrong ID: got %v, want %v", n.ID(), rid)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/internal/testlog"
|
"github.com/ethereum/go-ethereum/internal/testlog"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/discover/v4wire"
|
||||||
"github.com/ethereum/go-ethereum/p2p/discover/v5wire"
|
"github.com/ethereum/go-ethereum/p2p/discover/v5wire"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||||
|
|
@ -576,7 +577,7 @@ func TestUDPv5_lookup(t *testing.T) {
|
||||||
test := newUDPV5Test(t)
|
test := newUDPV5Test(t)
|
||||||
|
|
||||||
// Lookup on empty table returns no nodes.
|
// Lookup on empty table returns no nodes.
|
||||||
if results := test.udp.Lookup(lookupTestnet.target.id()); len(results) > 0 {
|
if results := test.udp.Lookup(lookupTestnet.target.ID()); len(results) > 0 {
|
||||||
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
|
t.Fatalf("lookup on empty table returned %d results: %#v", len(results), results)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -596,7 +597,7 @@ func TestUDPv5_lookup(t *testing.T) {
|
||||||
// Start the lookup.
|
// Start the lookup.
|
||||||
resultC := make(chan []*enode.Node, 1)
|
resultC := make(chan []*enode.Node, 1)
|
||||||
go func() {
|
go func() {
|
||||||
resultC <- test.udp.Lookup(lookupTestnet.target.id())
|
resultC <- test.udp.Lookup(lookupTestnet.target.ID())
|
||||||
test.close()
|
test.close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -793,7 +794,7 @@ func (test *udpV5Test) packetInFrom(key *ecdsa.PrivateKey, addr netip.AddrPort,
|
||||||
|
|
||||||
// getNode ensures the test knows about a node at the given endpoint.
|
// getNode ensures the test knows about a node at the given endpoint.
|
||||||
func (test *udpV5Test) getNode(key *ecdsa.PrivateKey, addr netip.AddrPort) *enode.LocalNode {
|
func (test *udpV5Test) getNode(key *ecdsa.PrivateKey, addr netip.AddrPort) *enode.LocalNode {
|
||||||
id := encodePubkey(&key.PublicKey).id()
|
id := v4wire.EncodePubkey(&key.PublicKey).ID()
|
||||||
ln := test.nodesByID[id]
|
ln := test.nodesByID[id]
|
||||||
if ln == nil {
|
if ln == nil {
|
||||||
db, _ := enode.OpenDB("")
|
db, _ := enode.OpenDB("")
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ func (v IPv4Addr) ENRKey() string { return "ip" }
|
||||||
func (v IPv4Addr) EncodeRLP(w io.Writer) error {
|
func (v IPv4Addr) EncodeRLP(w io.Writer) error {
|
||||||
addr := netip.Addr(v)
|
addr := netip.Addr(v)
|
||||||
if !addr.Is4() {
|
if !addr.Is4() {
|
||||||
return fmt.Errorf("address is not IPv4")
|
return errors.New("address is not IPv4")
|
||||||
}
|
}
|
||||||
enc := rlp.NewEncoderBuffer(w)
|
enc := rlp.NewEncoderBuffer(w)
|
||||||
bytes := addr.As4()
|
bytes := addr.As4()
|
||||||
|
|
@ -204,7 +204,7 @@ func (v IPv6Addr) ENRKey() string { return "ip6" }
|
||||||
func (v IPv6Addr) EncodeRLP(w io.Writer) error {
|
func (v IPv6Addr) EncodeRLP(w io.Writer) error {
|
||||||
addr := netip.Addr(v)
|
addr := netip.Addr(v)
|
||||||
if !addr.Is6() {
|
if !addr.Is6() {
|
||||||
return fmt.Errorf("address is not IPv6")
|
return errors.New("address is not IPv6")
|
||||||
}
|
}
|
||||||
enc := rlp.NewEncoderBuffer(w)
|
enc := rlp.NewEncoderBuffer(w)
|
||||||
bytes := addr.As16()
|
bytes := addr.As16()
|
||||||
|
|
|
||||||
|
|
@ -138,8 +138,10 @@ func (n ExtIP) String() string { return fmt.Sprintf("ExtIP(%v)", ne
|
||||||
|
|
||||||
// These do nothing.
|
// These do nothing.
|
||||||
|
|
||||||
func (ExtIP) AddMapping(string, int, int, string, time.Duration) (uint16, error) { return 0, nil }
|
func (ExtIP) AddMapping(protocol string, extport, intport int, name string, lifetime time.Duration) (uint16, error) {
|
||||||
func (ExtIP) DeleteMapping(string, int, int) error { return nil }
|
return uint16(extport), nil
|
||||||
|
}
|
||||||
|
func (ExtIP) DeleteMapping(string, int, int) error { return nil }
|
||||||
|
|
||||||
// Any returns a port mapper that tries to discover any supported
|
// Any returns a port mapper that tries to discover any supported
|
||||||
// mechanism on the local network.
|
// mechanism on the local network.
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ func (srv *Server) portMappingLoop() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("Couldn't get external IP", "err", err, "interface", srv.NAT)
|
log.Debug("Couldn't get external IP", "err", err, "interface", srv.NAT)
|
||||||
} else if !ip.Equal(lastExtIP) {
|
} else if !ip.Equal(lastExtIP) {
|
||||||
log.Debug("External IP changed", "ip", extip, "interface", srv.NAT)
|
log.Debug("External IP changed", "ip", ip, "interface", srv.NAT)
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ func TestServerPortMapping(t *testing.T) {
|
||||||
PrivateKey: newkey(),
|
PrivateKey: newkey(),
|
||||||
NoDial: true,
|
NoDial: true,
|
||||||
ListenAddr: ":0",
|
ListenAddr: ":0",
|
||||||
|
DiscAddr: ":0",
|
||||||
NAT: mockNAT,
|
NAT: mockNAT,
|
||||||
Logger: testlog.Logger(t, log.LvlTrace),
|
Logger: testlog.Logger(t, log.LvlTrace),
|
||||||
clock: clock,
|
clock: clock,
|
||||||
|
|
|
||||||
|
|
@ -24,44 +24,13 @@ const (
|
||||||
// contains on the server side.
|
// contains on the server side.
|
||||||
BloomBitsBlocks uint64 = 4096
|
BloomBitsBlocks uint64 = 4096
|
||||||
|
|
||||||
// BloomBitsBlocksClient is the number of blocks a single bloom bit section vector
|
|
||||||
// contains on the light client side
|
|
||||||
BloomBitsBlocksClient uint64 = 32768
|
|
||||||
|
|
||||||
// BloomConfirms is the number of confirmation blocks before a bloom section is
|
// BloomConfirms is the number of confirmation blocks before a bloom section is
|
||||||
// considered probably final and its rotated bits are calculated.
|
// considered probably final and its rotated bits are calculated.
|
||||||
BloomConfirms = 256
|
BloomConfirms = 256
|
||||||
|
|
||||||
// CHTFrequency is the block frequency for creating CHTs
|
|
||||||
CHTFrequency = 32768
|
|
||||||
|
|
||||||
// BloomTrieFrequency is the block frequency for creating BloomTrie on both
|
|
||||||
// server/client sides.
|
|
||||||
BloomTrieFrequency = 32768
|
|
||||||
|
|
||||||
// HelperTrieConfirmations is the number of confirmations before a client is expected
|
|
||||||
// to have the given HelperTrie available.
|
|
||||||
HelperTrieConfirmations = 2048
|
|
||||||
|
|
||||||
// HelperTrieProcessConfirmations is the number of confirmations before a HelperTrie
|
|
||||||
// is generated
|
|
||||||
HelperTrieProcessConfirmations = 256
|
|
||||||
|
|
||||||
// CheckpointFrequency is the block frequency for creating checkpoint
|
|
||||||
CheckpointFrequency = 32768
|
|
||||||
|
|
||||||
// CheckpointProcessConfirmations is the number before a checkpoint is generated
|
|
||||||
CheckpointProcessConfirmations = 256
|
|
||||||
|
|
||||||
// FullImmutabilityThreshold is the number of blocks after which a chain segment is
|
// FullImmutabilityThreshold is the number of blocks after which a chain segment is
|
||||||
// considered immutable (i.e. soft finality). It is used by the downloader as a
|
// considered immutable (i.e. soft finality). It is used by the downloader as a
|
||||||
// hard limit against deep ancestors, by the blockchain against deep reorgs, by
|
// hard limit against deep ancestors, by the blockchain against deep reorgs, by
|
||||||
// the freezer as the cutoff threshold and by clique as the snapshot trust limit.
|
// the freezer as the cutoff threshold and by clique as the snapshot trust limit.
|
||||||
FullImmutabilityThreshold = 90000
|
FullImmutabilityThreshold = 90000
|
||||||
|
|
||||||
// LightImmutabilityThreshold is the number of blocks after which a header chain
|
|
||||||
// segment is considered immutable for light client(i.e. soft finality). It is used by
|
|
||||||
// the downloader as a hard limit against deep ancestors, by the blockchain against deep
|
|
||||||
// reorgs, by the light pruner as the pruning validity guarantee.
|
|
||||||
LightImmutabilityThreshold = 30000
|
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import (
|
||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 14 // Minor version component of the current release
|
VersionMinor = 14 // Minor version component of the current release
|
||||||
VersionPatch = 7 // Patch version component of the current release
|
VersionPatch = 8 // Patch version component of the current release
|
||||||
VersionMeta = "unstable" // Version metadata to append to the version string
|
VersionMeta = "unstable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,9 @@ package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
|
@ -151,8 +153,8 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) {
|
||||||
|
|
||||||
reqs, batch, err := codec.readBatch()
|
reqs, batch, err := codec.readBatch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != io.EOF {
|
if msg := messageForReadError(err); msg != "" {
|
||||||
resp := errorMessage(&invalidMessageError{"parse error"})
|
resp := errorMessage(&invalidMessageError{msg})
|
||||||
codec.writeJSON(ctx, resp, true)
|
codec.writeJSON(ctx, resp, true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
@ -164,6 +166,20 @@ func (s *Server) serveSingleRequest(ctx context.Context, codec ServerCodec) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func messageForReadError(err error) string {
|
||||||
|
var netErr net.Error
|
||||||
|
if errors.As(err, &netErr) {
|
||||||
|
if netErr.Timeout() {
|
||||||
|
return "read timeout"
|
||||||
|
} else {
|
||||||
|
return "read error"
|
||||||
|
}
|
||||||
|
} else if err != io.EOF {
|
||||||
|
return "parse error"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// Stop stops reading new requests, waits for stopPendingRequestTimeout to allow pending
|
// Stop stops reading new requests, waits for stopPendingRequestTimeout to allow pending
|
||||||
// requests to finish, then closes all codecs which will cancel pending requests and
|
// requests to finish, then closes all codecs which will cancel pending requests and
|
||||||
// subscriptions.
|
// subscriptions.
|
||||||
|
|
|
||||||
|
|
@ -267,13 +267,9 @@ func TestNotify(t *testing.T) {
|
||||||
sub: &Subscription{ID: id},
|
sub: &Subscription{ID: id},
|
||||||
activated: true,
|
activated: true,
|
||||||
}
|
}
|
||||||
msg := &types.Header{
|
notifier.Notify(id, "hello")
|
||||||
ParentHash: common.HexToHash("0x01"),
|
|
||||||
Number: big.NewInt(100),
|
|
||||||
}
|
|
||||||
notifier.Notify(id, msg)
|
|
||||||
have := strings.TrimSpace(out.String())
|
have := strings.TrimSpace(out.String())
|
||||||
want := `{"jsonrpc":"2.0","method":"_subscription","params":{"subscription":"test","result":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000001","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":null,"number":"0x64","gasLimit":"0x0","gasUsed":"0x0","timestamp":"0x0","extraData":"0x","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":null,"withdrawalsRoot":null,"blobGasUsed":null,"excessBlobGas":null,"parentBeaconBlockRoot":null,"hash":"0xe5fb877dde471b45b9742bb4bb4b3d74a761e2fb7cb849a3d2b687eed90fb604"}}}`
|
want := `{"jsonrpc":"2.0","method":"_subscription","params":{"subscription":"test","result":"hello"}}`
|
||||||
if have != want {
|
if have != want {
|
||||||
t.Errorf("have:\n%v\nwant:\n%v\n", have, want)
|
t.Errorf("have:\n%v\nwant:\n%v\n", have, want)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -154,12 +154,8 @@ func (c *committer) store(path []byte, n node) node {
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
// MerkleResolver the children resolver in merkle-patricia-tree.
|
// ForGatherChildren decodes the provided node and traverses the children inside.
|
||||||
type MerkleResolver struct{}
|
func ForGatherChildren(node []byte, onChild func(common.Hash)) {
|
||||||
|
|
||||||
// ForEach implements childResolver, decodes the provided node and
|
|
||||||
// traverses the children inside.
|
|
||||||
func (resolver MerkleResolver) ForEach(node []byte, onChild func(common.Hash)) {
|
|
||||||
forGatherChildren(mustDecodeNodeUnsafe(nil, node), onChild)
|
forGatherChildren(mustDecodeNodeUnsafe(nil, node), onChild)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -819,7 +819,6 @@ func (s *spongeDb) Get(key []byte) ([]byte, error) { return nil, error
|
||||||
func (s *spongeDb) Delete(key []byte) error { panic("implement me") }
|
func (s *spongeDb) Delete(key []byte) error { panic("implement me") }
|
||||||
func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} }
|
func (s *spongeDb) NewBatch() ethdb.Batch { return &spongeBatch{s} }
|
||||||
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
|
func (s *spongeDb) NewBatchWithSize(size int) ethdb.Batch { return &spongeBatch{s} }
|
||||||
func (s *spongeDb) NewSnapshot() (ethdb.Snapshot, error) { panic("implement me") }
|
|
||||||
func (s *spongeDb) Stat() (string, error) { panic("implement me") }
|
func (s *spongeDb) Stat() (string, error) { panic("implement me") }
|
||||||
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
|
func (s *spongeDb) Compact(start []byte, limit []byte) error { panic("implement me") }
|
||||||
func (s *spongeDb) Close() error { return nil }
|
func (s *spongeDb) Close() error { return nil }
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,57 @@ func (t *VerkleTrie) DeleteAccount(addr common.Address) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RollBackAccount removes the account info + code from the tree, unlike DeleteAccount
|
||||||
|
// that will overwrite it with 0s. The first 64 storage slots are also removed.
|
||||||
|
func (t *VerkleTrie) RollBackAccount(addr common.Address) error {
|
||||||
|
var (
|
||||||
|
evaluatedAddr = t.cache.Get(addr.Bytes())
|
||||||
|
codeSizeKey = utils.CodeSizeKeyWithEvaluatedAddress(evaluatedAddr)
|
||||||
|
)
|
||||||
|
codeSizeBytes, err := t.root.Get(codeSizeKey, t.nodeResolver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("rollback: error finding code size: %w", err)
|
||||||
|
}
|
||||||
|
if len(codeSizeBytes) == 0 {
|
||||||
|
return errors.New("rollback: code size is not existent")
|
||||||
|
}
|
||||||
|
codeSize := binary.LittleEndian.Uint64(codeSizeBytes)
|
||||||
|
|
||||||
|
// Delete the account header + first 64 slots + first 128 code chunks
|
||||||
|
key := common.CopyBytes(codeSizeKey)
|
||||||
|
for i := 0; i < verkle.NodeWidth; i++ {
|
||||||
|
key[31] = byte(i)
|
||||||
|
|
||||||
|
// this is a workaround to avoid deleting nil leaves, the lib needs to be
|
||||||
|
// fixed to be able to handle that
|
||||||
|
v, err := t.root.Get(key, t.nodeResolver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error rolling back account header: %w", err)
|
||||||
|
}
|
||||||
|
if len(v) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, err = t.root.Delete(key, t.nodeResolver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error rolling back account header: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Delete all further code
|
||||||
|
for i, chunknr := uint64(32*128), uint64(128); i < codeSize; i, chunknr = i+32, chunknr+1 {
|
||||||
|
// evaluate group key at the start of a new group
|
||||||
|
groupOffset := (chunknr + 128) % 256
|
||||||
|
if groupOffset == 0 {
|
||||||
|
key = utils.CodeChunkKeyWithEvaluatedAddress(evaluatedAddr, uint256.NewInt(chunknr))
|
||||||
|
}
|
||||||
|
key[31] = byte(groupOffset)
|
||||||
|
_, err = t.root.Delete(key[:], t.nodeResolver)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error deleting code chunk (addr=%x) error: %w", addr[:], err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteStorage implements state.Trie, deleting the specified storage slot from
|
// DeleteStorage implements state.Trie, deleting the specified storage slot from
|
||||||
// the trie. If the storage slot was not existent in the trie, no error will be
|
// the trie. If the storage slot was not existent in the trie, no error will be
|
||||||
// returned. If the trie is corrupted, an error will be returned.
|
// returned. If the trie is corrupted, an error will be returned.
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/trie/utils"
|
"github.com/ethereum/go-ethereum/trie/utils"
|
||||||
"github.com/holiman/uint256"
|
"github.com/holiman/uint256"
|
||||||
)
|
)
|
||||||
|
|
@ -89,3 +90,84 @@ func TestVerkleTreeReadWrite(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVerkleRollBack(t *testing.T) {
|
||||||
|
db := newTestDatabase(rawdb.NewMemoryDatabase(), rawdb.PathScheme)
|
||||||
|
tr, _ := NewVerkleTrie(types.EmptyVerkleHash, db, utils.NewPointCache(100))
|
||||||
|
|
||||||
|
for addr, acct := range accounts {
|
||||||
|
if err := tr.UpdateAccount(addr, acct); err != nil {
|
||||||
|
t.Fatalf("Failed to update account, %v", err)
|
||||||
|
}
|
||||||
|
for key, val := range storages[addr] {
|
||||||
|
if err := tr.UpdateStorage(addr, key.Bytes(), val); err != nil {
|
||||||
|
t.Fatalf("Failed to update account, %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create more than 128 chunks of code
|
||||||
|
code := make([]byte, 129*32)
|
||||||
|
for i := 0; i < len(code); i += 2 {
|
||||||
|
code[i] = 0x60
|
||||||
|
code[i+1] = byte(i % 256)
|
||||||
|
}
|
||||||
|
hash := crypto.Keccak256Hash(code)
|
||||||
|
if err := tr.UpdateContractCode(addr, hash, code); err != nil {
|
||||||
|
t.Fatalf("Failed to update contract, %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that things were created
|
||||||
|
for addr, acct := range accounts {
|
||||||
|
stored, err := tr.GetAccount(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get account, %v", err)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(stored, acct) {
|
||||||
|
t.Fatal("account is not matched")
|
||||||
|
}
|
||||||
|
for key, val := range storages[addr] {
|
||||||
|
stored, err := tr.GetStorage(addr, key.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get storage, %v", err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(stored, val) {
|
||||||
|
t.Fatal("storage is not matched")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure there is some code in the 2nd group
|
||||||
|
keyOf2ndGroup := []byte{141, 124, 185, 236, 50, 22, 185, 39, 244, 47, 97, 209, 96, 235, 22, 13, 205, 38, 18, 201, 128, 223, 0, 59, 146, 199, 222, 119, 133, 13, 91, 0}
|
||||||
|
chunk, err := tr.root.Get(keyOf2ndGroup, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get account, %v", err)
|
||||||
|
}
|
||||||
|
if len(chunk) == 0 {
|
||||||
|
t.Fatal("account was not created ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rollback first account and check that it is gone
|
||||||
|
addr1 := common.Address{1}
|
||||||
|
err = tr.RollBackAccount(addr1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error rolling back address 1: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure the account is gone
|
||||||
|
stored, err := tr.GetAccount(addr1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get account, %v", err)
|
||||||
|
}
|
||||||
|
if stored != nil {
|
||||||
|
t.Fatal("account was not deleted")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that the last code chunk is also gone from the tree
|
||||||
|
chunk, err = tr.root.Get(keyOf2ndGroup, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get account, %v", err)
|
||||||
|
}
|
||||||
|
if len(chunk) != 0 {
|
||||||
|
t.Fatal("account was not deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||||
"github.com/ethereum/go-ethereum/triedb/database"
|
"github.com/ethereum/go-ethereum/triedb/database"
|
||||||
|
|
@ -43,9 +42,18 @@ type Config struct {
|
||||||
// default settings.
|
// default settings.
|
||||||
var HashDefaults = &Config{
|
var HashDefaults = &Config{
|
||||||
Preimages: false,
|
Preimages: false,
|
||||||
|
IsVerkle: false,
|
||||||
HashDB: hashdb.Defaults,
|
HashDB: hashdb.Defaults,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerkleDefaults represents a config for holding verkle trie data
|
||||||
|
// using path-based scheme with default settings.
|
||||||
|
var VerkleDefaults = &Config{
|
||||||
|
Preimages: false,
|
||||||
|
IsVerkle: true,
|
||||||
|
PathDB: pathdb.Defaults,
|
||||||
|
}
|
||||||
|
|
||||||
// backend defines the methods needed to access/update trie nodes in different
|
// backend defines the methods needed to access/update trie nodes in different
|
||||||
// state scheme.
|
// state scheme.
|
||||||
type backend interface {
|
type backend interface {
|
||||||
|
|
@ -85,7 +93,6 @@ type backend interface {
|
||||||
// relevant with trie nodes and node preimages.
|
// relevant with trie nodes and node preimages.
|
||||||
type Database struct {
|
type Database struct {
|
||||||
config *Config // Configuration for trie database
|
config *Config // Configuration for trie database
|
||||||
diskdb ethdb.Database // Persistent database to store the snapshot
|
|
||||||
preimages *preimageStore // The store for caching preimages
|
preimages *preimageStore // The store for caching preimages
|
||||||
backend backend // The backend for managing trie nodes
|
backend backend // The backend for managing trie nodes
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +110,6 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
|
||||||
}
|
}
|
||||||
db := &Database{
|
db := &Database{
|
||||||
config: config,
|
config: config,
|
||||||
diskdb: diskdb,
|
|
||||||
preimages: preimages,
|
preimages: preimages,
|
||||||
}
|
}
|
||||||
if config.HashDB != nil && config.PathDB != nil {
|
if config.HashDB != nil && config.PathDB != nil {
|
||||||
|
|
@ -112,14 +118,7 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database {
|
||||||
if config.PathDB != nil {
|
if config.PathDB != nil {
|
||||||
db.backend = pathdb.New(diskdb, config.PathDB, config.IsVerkle)
|
db.backend = pathdb.New(diskdb, config.PathDB, config.IsVerkle)
|
||||||
} else {
|
} else {
|
||||||
var resolver hashdb.ChildResolver
|
db.backend = hashdb.New(diskdb, config.HashDB)
|
||||||
if config.IsVerkle {
|
|
||||||
// TODO define verkle resolver
|
|
||||||
log.Crit("verkle does not use a hash db")
|
|
||||||
} else {
|
|
||||||
resolver = trie.MerkleResolver{}
|
|
||||||
}
|
|
||||||
db.backend = hashdb.New(diskdb, config.HashDB, resolver)
|
|
||||||
}
|
}
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/metrics"
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
"github.com/ethereum/go-ethereum/trie/trienode"
|
"github.com/ethereum/go-ethereum/trie/trienode"
|
||||||
"github.com/ethereum/go-ethereum/trie/triestate"
|
"github.com/ethereum/go-ethereum/trie/triestate"
|
||||||
"github.com/ethereum/go-ethereum/triedb/database"
|
"github.com/ethereum/go-ethereum/triedb/database"
|
||||||
|
|
@ -60,12 +61,6 @@ var (
|
||||||
memcacheCommitBytesMeter = metrics.NewRegisteredMeter("hashdb/memcache/commit/bytes", nil)
|
memcacheCommitBytesMeter = metrics.NewRegisteredMeter("hashdb/memcache/commit/bytes", nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
// ChildResolver defines the required method to decode the provided
|
|
||||||
// trie node and iterate the children on top.
|
|
||||||
type ChildResolver interface {
|
|
||||||
ForEach(node []byte, onChild func(common.Hash))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config contains the settings for database.
|
// Config contains the settings for database.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes
|
CleanCacheSize int // Maximum memory allowance (in bytes) for caching clean nodes
|
||||||
|
|
@ -84,9 +79,7 @@ var Defaults = &Config{
|
||||||
// the disk database. The aim is to accumulate trie writes in-memory and only
|
// the disk database. The aim is to accumulate trie writes in-memory and only
|
||||||
// periodically flush a couple tries to disk, garbage collecting the remainder.
|
// periodically flush a couple tries to disk, garbage collecting the remainder.
|
||||||
type Database struct {
|
type Database struct {
|
||||||
diskdb ethdb.Database // Persistent storage for matured trie nodes
|
diskdb ethdb.Database // Persistent storage for matured trie nodes
|
||||||
resolver ChildResolver // The handler to resolve children of nodes
|
|
||||||
|
|
||||||
cleans *fastcache.Cache // GC friendly memory cache of clean node RLPs
|
cleans *fastcache.Cache // GC friendly memory cache of clean node RLPs
|
||||||
dirties map[common.Hash]*cachedNode // Data and references relationships of dirty trie nodes
|
dirties map[common.Hash]*cachedNode // Data and references relationships of dirty trie nodes
|
||||||
oldest common.Hash // Oldest tracked node, flush-list head
|
oldest common.Hash // Oldest tracked node, flush-list head
|
||||||
|
|
@ -124,15 +117,15 @@ var cachedNodeSize = int(reflect.TypeOf(cachedNode{}).Size())
|
||||||
// forChildren invokes the callback for all the tracked children of this node,
|
// forChildren invokes the callback for all the tracked children of this node,
|
||||||
// both the implicit ones from inside the node as well as the explicit ones
|
// both the implicit ones from inside the node as well as the explicit ones
|
||||||
// from outside the node.
|
// from outside the node.
|
||||||
func (n *cachedNode) forChildren(resolver ChildResolver, onChild func(hash common.Hash)) {
|
func (n *cachedNode) forChildren(onChild func(hash common.Hash)) {
|
||||||
for child := range n.external {
|
for child := range n.external {
|
||||||
onChild(child)
|
onChild(child)
|
||||||
}
|
}
|
||||||
resolver.ForEach(n.node, onChild)
|
trie.ForGatherChildren(n.node, onChild)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New initializes the hash-based node database.
|
// New initializes the hash-based node database.
|
||||||
func New(diskdb ethdb.Database, config *Config, resolver ChildResolver) *Database {
|
func New(diskdb ethdb.Database, config *Config) *Database {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
config = Defaults
|
config = Defaults
|
||||||
}
|
}
|
||||||
|
|
@ -141,10 +134,9 @@ func New(diskdb ethdb.Database, config *Config, resolver ChildResolver) *Databas
|
||||||
cleans = fastcache.New(config.CleanCacheSize)
|
cleans = fastcache.New(config.CleanCacheSize)
|
||||||
}
|
}
|
||||||
return &Database{
|
return &Database{
|
||||||
diskdb: diskdb,
|
diskdb: diskdb,
|
||||||
resolver: resolver,
|
cleans: cleans,
|
||||||
cleans: cleans,
|
dirties: make(map[common.Hash]*cachedNode),
|
||||||
dirties: make(map[common.Hash]*cachedNode),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,7 +155,7 @@ func (db *Database) insert(hash common.Hash, node []byte) {
|
||||||
node: node,
|
node: node,
|
||||||
flushPrev: db.newest,
|
flushPrev: db.newest,
|
||||||
}
|
}
|
||||||
entry.forChildren(db.resolver, func(child common.Hash) {
|
entry.forChildren(func(child common.Hash) {
|
||||||
if c := db.dirties[child]; c != nil {
|
if c := db.dirties[child]; c != nil {
|
||||||
c.parents++
|
c.parents++
|
||||||
}
|
}
|
||||||
|
|
@ -316,7 +308,7 @@ func (db *Database) dereference(hash common.Hash) {
|
||||||
db.dirties[node.flushNext].flushPrev = node.flushPrev
|
db.dirties[node.flushNext].flushPrev = node.flushPrev
|
||||||
}
|
}
|
||||||
// Dereference all children and delete the node
|
// Dereference all children and delete the node
|
||||||
node.forChildren(db.resolver, func(child common.Hash) {
|
node.forChildren(func(child common.Hash) {
|
||||||
db.dereference(child)
|
db.dereference(child)
|
||||||
})
|
})
|
||||||
delete(db.dirties, hash)
|
delete(db.dirties, hash)
|
||||||
|
|
@ -465,7 +457,7 @@ func (db *Database) commit(hash common.Hash, batch ethdb.Batch, uncacher *cleane
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Dereference all children and delete the node
|
// Dereference all children and delete the node
|
||||||
node.forChildren(db.resolver, func(child common.Hash) {
|
node.forChildren(func(child common.Hash) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = db.commit(child, batch, uncacher)
|
err = db.commit(child, batch, uncacher)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,14 @@ func New(diskdb ethdb.Database, config *Config, isVerkle bool) *Database {
|
||||||
}
|
}
|
||||||
config = config.sanitize()
|
config = config.sanitize()
|
||||||
|
|
||||||
|
// Establish a dedicated database namespace tailored for verkle-specific
|
||||||
|
// data, ensuring the isolation of both verkle and merkle tree data. It's
|
||||||
|
// important to note that the introduction of a prefix won't lead to
|
||||||
|
// substantial storage overhead, as the underlying database will efficiently
|
||||||
|
// compress the shared key prefix.
|
||||||
|
if isVerkle {
|
||||||
|
diskdb = rawdb.NewTable(diskdb, string(rawdb.VerklePrefix))
|
||||||
|
}
|
||||||
db := &Database{
|
db := &Database{
|
||||||
readOnly: config.ReadOnly,
|
readOnly: config.ReadOnly,
|
||||||
isVerkle: isVerkle,
|
isVerkle: isVerkle,
|
||||||
|
|
@ -190,7 +198,7 @@ func (db *Database) repairHistory() error {
|
||||||
// all of them. Fix the tests first.
|
// all of them. Fix the tests first.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
freezer, err := rawdb.NewStateFreezer(ancient, db.readOnly)
|
freezer, err := rawdb.NewStateFreezer(ancient, db.isVerkle, db.readOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Crit("Failed to open state history freezer", "err", err)
|
log.Crit("Failed to open state history freezer", "err", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ func TestTruncateHeadHistory(t *testing.T) {
|
||||||
roots []common.Hash
|
roots []common.Hash
|
||||||
hs = makeHistories(10)
|
hs = makeHistories(10)
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false)
|
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false)
|
||||||
)
|
)
|
||||||
defer freezer.Close()
|
defer freezer.Close()
|
||||||
|
|
||||||
|
|
@ -157,7 +157,7 @@ func TestTruncateTailHistory(t *testing.T) {
|
||||||
roots []common.Hash
|
roots []common.Hash
|
||||||
hs = makeHistories(10)
|
hs = makeHistories(10)
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false)
|
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false)
|
||||||
)
|
)
|
||||||
defer freezer.Close()
|
defer freezer.Close()
|
||||||
|
|
||||||
|
|
@ -200,7 +200,7 @@ func TestTruncateTailHistories(t *testing.T) {
|
||||||
roots []common.Hash
|
roots []common.Hash
|
||||||
hs = makeHistories(10)
|
hs = makeHistories(10)
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
freezer, _ = rawdb.NewStateFreezer(t.TempDir()+fmt.Sprintf("%d", i), false)
|
freezer, _ = rawdb.NewStateFreezer(t.TempDir()+fmt.Sprintf("%d", i), false, false)
|
||||||
)
|
)
|
||||||
defer freezer.Close()
|
defer freezer.Close()
|
||||||
|
|
||||||
|
|
@ -228,7 +228,7 @@ func TestTruncateOutOfRange(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
hs = makeHistories(10)
|
hs = makeHistories(10)
|
||||||
db = rawdb.NewMemoryDatabase()
|
db = rawdb.NewMemoryDatabase()
|
||||||
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false)
|
freezer, _ = rawdb.NewStateFreezer(t.TempDir(), false, false)
|
||||||
)
|
)
|
||||||
defer freezer.Close()
|
defer freezer.Close()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ func (r *reader) Node(owner common.Hash, path []byte, hash common.Hash) ([]byte,
|
||||||
if len(blob) > 0 {
|
if len(blob) > 0 {
|
||||||
blobHex = hexutil.Encode(blob)
|
blobHex = hexutil.Encode(blob)
|
||||||
}
|
}
|
||||||
log.Error("Unexpected trie node", "location", loc.loc, "owner", owner, "path", path, "expect", hash, "got", got, "blob", blobHex)
|
log.Error("Unexpected trie node", "location", loc.loc, "owner", owner.Hex(), "path", path, "expect", hash.Hex(), "got", got.Hex(), "blob", blobHex)
|
||||||
return nil, fmt.Errorf("unexpected node: (%x %v), %x!=%x, %s, blob: %s", owner, path, hash, got, loc.string(), blobHex)
|
return nil, fmt.Errorf("unexpected node: (%x %v), %x!=%x, %s, blob: %s", owner, path, hash, got, loc.string(), blobHex)
|
||||||
}
|
}
|
||||||
return blob, nil
|
return blob, nil
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue