Merge pull request #57 from DeBankDeFi/merge_upstream_v1.11.2

Merge upstream v1.11.2
This commit is contained in:
cifer76 2023-03-07 17:33:18 +03:00 committed by GitHub
commit 29d43c9ac2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
95 changed files with 684 additions and 429 deletions

View file

@ -8,15 +8,13 @@ jobs:
go: 1.17.x go: 1.17.x
env: env:
- azure-osx - azure-osx
- azure-ios
- cocoapods-ios
include: include:
# This builder only tests code linters on latest version of Go # This builder only tests code linters on latest version of Go
- stage: lint - stage: lint
os: linux os: linux
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- lint - lint
git: git:
@ -31,7 +29,7 @@ jobs:
os: linux os: linux
arch: amd64 arch: amd64
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- docker - docker
services: services:
@ -48,7 +46,7 @@ jobs:
os: linux os: linux
arch: arm64 arch: arm64
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- docker - docker
services: services:
@ -65,7 +63,7 @@ jobs:
if: type = push if: type = push
os: linux os: linux
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- ubuntu-ppa - ubuntu-ppa
- GO111MODULE=on - GO111MODULE=on
@ -90,7 +88,7 @@ jobs:
os: linux os: linux
dist: bionic dist: bionic
sudo: required sudo: required
go: 1.19.x go: 1.20.x
env: env:
- azure-linux - azure-linux
- GO111MODULE=on - GO111MODULE=on
@ -120,12 +118,26 @@ jobs:
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc - go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# This builder does the OSX Azure uploads
- stage: build
if: type = push
os: osx
go: 1.20.x
env:
- azure-osx
- GO111MODULE=on
git:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go install -dlgo
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
# These builders run the tests # These builders run the tests
- stage: build - stage: build
os: linux os: linux
arch: amd64 arch: amd64
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:
@ -136,7 +148,7 @@ jobs:
os: linux os: linux
arch: arm64 arch: arm64
dist: bionic dist: bionic
go: 1.18.x go: 1.19.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:
@ -145,7 +157,7 @@ jobs:
- stage: build - stage: build
os: linux os: linux
dist: bionic dist: bionic
go: 1.18.x go: 1.19.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:
@ -156,7 +168,7 @@ jobs:
if: type = cron if: type = cron
os: linux os: linux
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- azure-purge - azure-purge
- GO111MODULE=on - GO111MODULE=on
@ -170,7 +182,7 @@ jobs:
if: type = cron if: type = cron
os: linux os: linux
dist: bionic dist: bionic
go: 1.19.x go: 1.20.x
env: env:
- GO111MODULE=on - GO111MODULE=on
script: script:

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM="" ARG BUILDNUM=""
# Build Geth in a stock Go builder container # Build Geth in a stock Go builder container
FROM golang:1.19-alpine as builder FROM golang:1.20-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git RUN apk add --no-cache gcc musl-dev linux-headers git

View file

@ -4,7 +4,7 @@ ARG VERSION=""
ARG BUILDNUM="" ARG BUILDNUM=""
# Build Geth in a stock Go builder container # Build Geth in a stock Go builder container
FROM golang:1.19-alpine as builder FROM golang:1.20-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git RUN apk add --no-cache gcc musl-dev linux-headers git

View file

@ -113,7 +113,6 @@ 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.
rand.Seed(time.Now().UnixNano())
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int())) dir := filepath.Join(os.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()
@ -322,7 +321,6 @@ func TestUpdatedKeyfileContents(t *testing.T) {
t.Parallel() t.Parallel()
// Create a temporary keystore to test with // Create a temporary keystore to test with
rand.Seed(time.Now().UnixNano())
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int())) dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int()))
ks := NewKeyStore(dir, LightScryptN, LightScryptP) ks := NewKeyStore(dir, LightScryptN, LightScryptP)

View file

@ -74,12 +74,11 @@ var (
// - newPayloadV1: if the payload was accepted, but not processed (side chain) // - newPayloadV1: if the payload was accepted, but not processed (side chain)
ACCEPTED = "ACCEPTED" ACCEPTED = "ACCEPTED"
INVALIDBLOCKHASH = "INVALID_BLOCK_HASH"
GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"} GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"}
UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"} UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"}
InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"} InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"}
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"} InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"} InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil} STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}

View file

@ -1,19 +1,19 @@
# This file contains sha256 checksums of optional build dependencies. # This file contains sha256 checksums of optional build dependencies.
8e486e8e85a281fc5ce3f0bedc5b9d2dbf6276d7db0b25d3ec034f313da0375f go1.19.5.src.tar.gz b5c1a3af52c385a6d1c76aed5361cf26459023980d0320de7658bae3915831a2 go1.20.1.src.tar.gz
23d22bb6571bbd60197bee8aaa10e702f9802786c2e2ddce5c84527e86b66aa0 go1.19.5.darwin-amd64.tar.gz a300a45e801ab459f3008aae5bb9efbe9a6de9bcd12388f5ca9bbd14f70236de go1.20.1.darwin-amd64.tar.gz
4a67f2bf0601afe2177eb58f825adf83509511d77ab79174db0712dc9efa16c8 go1.19.5.darwin-arm64.tar.gz f1a8e06c7f1ba1c008313577f3f58132eb166a41ceb95ce6e9af30bc5a3efca4 go1.20.1.darwin-arm64.tar.gz
b18a5e1e60130003896e1d1c8a9e142c7cccf6f5063d52c55dd42006434419c1 go1.19.5.freebsd-386.tar.gz 57d80349dc4fbf692f8cd85a5971f97841aedafcf211e367e59d3ae812292660 go1.20.1.freebsd-386.tar.gz
317996f7427691ff3a7ffd1b6aa089b9c66cd76f32e9107443f2f6aad1bb568a go1.19.5.freebsd-amd64.tar.gz 6e124d54d5850a15fdb15754f782986f06af23c5ddb6690849417b9c74f05f98 go1.20.1.freebsd-amd64.tar.gz
f68331aa7458a3598060595f5601d5731fd452bb2c62ff23095ddad68854e510 go1.19.5.linux-386.tar.gz 3a7345036ebd92455b653e4b4f6aaf4f7e1f91f4ced33b23d7059159cec5f4d7 go1.20.1.linux-386.tar.gz
36519702ae2fd573c9869461990ae550c8c0d955cd28d2827a6b159fda81ff95 go1.19.5.linux-amd64.tar.gz 000a5b1fca4f75895f78befeb2eecf10bfff3c428597f3f1e69133b63b911b02 go1.20.1.linux-amd64.tar.gz
fc0aa29c933cec8d76f5435d859aaf42249aa08c74eb2d154689ae44c08d23b3 go1.19.5.linux-arm64.tar.gz 5e5e2926733595e6f3c5b5ad1089afac11c1490351855e87849d0e7702b1ec2e go1.20.1.linux-arm64.tar.gz
ec14f04bdaf4a62bdcf8b55b9b6434cc27c2df7d214d0bb7076a7597283b026a go1.19.5.linux-armv6l.tar.gz e4edc05558ab3657ba3dddb909209463cee38df9c1996893dd08cde274915003 go1.20.1.linux-armv6l.tar.gz
e4032e7c52ebc48bad5c58ba8de0759b6091d9b1e59581a8a521c8c9d88dbe93 go1.19.5.linux-ppc64le.tar.gz 85cfd4b89b48c94030783b6e9e619e35557862358b846064636361421d0b0c52 go1.20.1.linux-ppc64le.tar.gz
764871cbca841a99a24e239b63c68a4aaff4104658e3165e9ca450cac1fcbea3 go1.19.5.linux-s390x.tar.gz ba3a14381ed4538216dec3ea72b35731750597edd851cece1eb120edf7d60149 go1.20.1.linux-s390x.tar.gz
8873f5871d996106b701febd979c5af022e6ea58bdbbb3817a28ab948b22c286 go1.19.5.windows-386.zip 61259b5a346193e30b7b3c3f8d108062db25bbb80cf290ee251eeb855965f6ee go1.20.1.windows-386.zip
167db91a2e40aeb453d3e59d213ecab06f62e1c4a84d13a06ccda1d999961caa go1.19.5.windows-amd64.zip 3b493969196a6de8d9762d09f5bc5ae7a3e5814b0cfbf9cc26838c2bc1314f9c go1.20.1.windows-amd64.zip
85a75555e82d8aa6f486d8d29491c593389682acce9f0c270090d5938eee30ef go1.19.5.windows-arm64.zip 62d14ddb44bcda27c9b1f5ad9ffd4463013374ed325d762417e2adefd59a802f go1.20.1.windows-arm64.zip
fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz fba08acc4027f69f07cef48fbff70b8a7ecdfaa1c2aba9ad3fb31d60d9f5d4bc golangci-lint-1.51.1-darwin-amd64.tar.gz
75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz 75b8f0ff3a4e68147156be4161a49d4576f1be37a0b506473f8c482140c1e7f2 golangci-lint-1.51.1-darwin-arm64.tar.gz
@ -41,3 +41,6 @@ c4f58b7e227b9fd41f0e9310dc83f4a4e7d026598e2f6e95b78761081a6d9bd2 golangci-lint-
eb57f9bcb56646f2e3d6ccaf02ec227815fb05077b2e0b1bf9e755805acdc2b9 golangci-lint-1.51.1-windows-arm64.zip eb57f9bcb56646f2e3d6ccaf02ec227815fb05077b2e0b1bf9e755805acdc2b9 golangci-lint-1.51.1-windows-arm64.zip
bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.zip bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.zip
cf6403f84707ce8c98664736772271bc8874f2e760c2fd0f00cf3e85963507e9 golangci-lint-1.51.1-windows-armv7.zip cf6403f84707ce8c98664736772271bc8874f2e760c2fd0f00cf3e85963507e9 golangci-lint-1.51.1-windows-armv7.zip
# This is the builder on PPA that will build Go itself (inception-y), don't modify!
d7f0013f82e6d7f862cc6cb5c8cdb48eef5f2e239b35baa97e2f1a7466043767 go1.19.6.src.tar.gz

View file

@ -132,7 +132,7 @@ var (
"focal": "golang-go", // EOL: 04/2030 "focal": "golang-go", // EOL: 04/2030
"jammy": "golang-go", // EOL: 04/2032 "jammy": "golang-go", // EOL: 04/2032
"kinetic": "golang-go", // EOL: 07/2023 "kinetic": "golang-go", // EOL: 07/2023
//"lunar": "golang-go", // EOL: 01/2024 "lunar": "golang-go", // EOL: 01/2024
} }
debGoBootPaths = map[string]string{ debGoBootPaths = map[string]string{
@ -140,10 +140,18 @@ var (
"golang-go": "/usr/lib/go", "golang-go": "/usr/lib/go",
} }
// This is the version of go that will be downloaded by // This is the version of Go that will be downloaded by
// //
// go run ci.go install -dlgo // go run ci.go install -dlgo
dlgoVersion = "1.19.5" dlgoVersion = "1.20.1"
// This is the version of Go that will be used to bootstrap the PPA builder.
//
// This version is fine to be old and full of security holes, we just use it
// to build the latest Go. Don't change it. If it ever becomes insufficient,
// we need to switch over to a recursive builder to jumpt across supported
// versions.
gobootVersion = "1.19.6"
) )
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@ -659,10 +667,11 @@ func doDebianSource(cmdline []string) {
gpg.Stdin = bytes.NewReader(key) gpg.Stdin = bytes.NewReader(key)
build.MustRun(gpg) build.MustRun(gpg)
} }
// Download and verify the Go source packages.
// Download and verify the Go source package. var (
gobundle := downloadGoSources(*cachedir) gobootbundle = downloadGoBootstrapSources(*cachedir)
gobundle = downloadGoSources(*cachedir)
)
// Download all the dependencies needed to build the sources and run the ci script // Download all the dependencies needed to build the sources and run the ci script
srcdepfetch := tc.Go("mod", "download") srcdepfetch := tc.Go("mod", "download")
srcdepfetch.Env = append(srcdepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath")) srcdepfetch.Env = append(srcdepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath"))
@ -679,12 +688,19 @@ func doDebianSource(cmdline []string) {
meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables) meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables)
pkgdir := stageDebianSource(*workdir, meta) pkgdir := stageDebianSource(*workdir, meta)
// Add Go source code // Add bootstrapper Go source code
if err := build.ExtractArchive(gobootbundle, pkgdir); err != nil {
log.Fatalf("Failed to extract bootstrapper Go sources: %v", err)
}
if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".goboot")); err != nil {
log.Fatalf("Failed to rename bootstrapper Go source folder: %v", err)
}
// Add builder Go source code
if err := build.ExtractArchive(gobundle, pkgdir); err != nil { if err := build.ExtractArchive(gobundle, pkgdir); err != nil {
log.Fatalf("Failed to extract Go sources: %v", err) log.Fatalf("Failed to extract builder Go sources: %v", err)
} }
if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil { if err := os.Rename(filepath.Join(pkgdir, "go"), filepath.Join(pkgdir, ".go")); err != nil {
log.Fatalf("Failed to rename Go source folder: %v", err) log.Fatalf("Failed to rename builder Go source folder: %v", err)
} }
// Add all dependency modules in compressed form // Add all dependency modules in compressed form
os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755) os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755)
@ -713,6 +729,19 @@ func doDebianSource(cmdline []string) {
} }
} }
// downloadGoBootstrapSources downloads the Go source tarball that will be used
// to bootstrap the builder Go.
func downloadGoBootstrapSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt")
file := fmt.Sprintf("go%s.src.tar.gz", gobootVersion)
url := "https://dl.google.com/go/" + file
dst := filepath.Join(cachedir, file)
if err := csdb.DownloadFile(url, dst); err != nil {
log.Fatal(err)
}
return dst
}
// downloadGoSources downloads the Go source tarball. // downloadGoSources downloads the Go source tarball.
func downloadGoSources(cachedir string) string { func downloadGoSources(cachedir string) string {
csdb := build.MustLoadChecksums("build/checksums.txt") csdb := build.MustLoadChecksums("build/checksums.txt")

View file

@ -16,7 +16,11 @@ override_dh_auto_build:
# We can't download a fresh Go within Launchpad, so we're shipping and building # We can't download a fresh Go within Launchpad, so we're shipping and building
# one on the fly. However, we can't build it inside the go-ethereum folder as # one on the fly. However, we can't build it inside the go-ethereum folder as
# bootstrapping clashes with go modules, so build in a sibling folder. # bootstrapping clashes with go modules, so build in a sibling folder.
(mv .go ../ && cd ../.go/src && ./make.bash) #
# We're also shipping the bootstrapper as of Go 1.20 as it had minimum version
# requirements opposed to older versions of Go.
(mv .goboot ../ && cd ../.goboot/src && ./make.bash)
(mv .go ../ && cd ../.go/src && GOROOT_BOOTSTRAP=`pwd`/../../.goboot ./make.bash)
# We can't download external go modules within Launchpad, so we're shipping the # We can't download external go modules within Launchpad, so we're shipping the
# entire dependency source cache with go-ethereum. # entire dependency source cache with go-ethereum.

View file

@ -23,6 +23,7 @@ import (
"math/rand" "math/rand"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/protocols/snap" "github.com/ethereum/go-ethereum/eth/protocols/snap"
"github.com/ethereum/go-ethereum/internal/utesting" "github.com/ethereum/go-ethereum/internal/utesting"
@ -210,13 +211,6 @@ type byteCodesTest struct {
expHashes int expHashes int
} }
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode = common.HexToHash("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
)
// TestSnapGetByteCodes various forms of GetByteCodes requests. // TestSnapGetByteCodes various forms of GetByteCodes requests.
func (s *Suite) TestSnapGetByteCodes(t *utesting.T) { func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
// The halfchain import should yield these bytecodes // The halfchain import should yield these bytecodes
@ -263,15 +257,15 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
}, },
// Empties // Empties
{ {
nBytes: 10000, hashes: []common.Hash{emptyRoot}, nBytes: 10000, hashes: []common.Hash{types.EmptyRootHash},
expHashes: 0, expHashes: 0,
}, },
{ {
nBytes: 10000, hashes: []common.Hash{emptyCode}, nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash},
expHashes: 1, expHashes: 1,
}, },
{ {
nBytes: 10000, hashes: []common.Hash{emptyCode, emptyCode, emptyCode}, nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash},
expHashes: 3, expHashes: 3,
}, },
// The existing bytecodes // The existing bytecodes
@ -363,7 +357,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
for i := 1; i <= 65; i++ { for i := 1; i <= 65; i++ {
accPaths = append(accPaths, pathTo(i)) accPaths = append(accPaths, pathTo(i))
} }
empty := emptyCode empty := types.EmptyCodeHash
for i, tc := range []trieNodesTest{ for i, tc := range []trieNodesTest{
{ {
root: s.chain.RootAt(999), root: s.chain.RootAt(999),

View file

@ -120,8 +120,8 @@ func (i *bbInput) ToBlock() *types.Block {
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{}, Coinbase: common.Address{},
Root: i.Header.Root, Root: i.Header.Root,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
Bloom: i.Header.Bloom, Bloom: i.Header.Bloom,
Difficulty: common.Big0, Difficulty: common.Big0,
Number: i.Header.Number, Number: i.Header.Number,

View file

@ -47,10 +47,10 @@ var (
dumpConfigCommand = &cli.Command{ dumpConfigCommand = &cli.Command{
Action: dumpConfig, Action: dumpConfig,
Name: "dumpconfig", Name: "dumpconfig",
Usage: "Show configuration values", Usage: "Export configuration values in a TOML format",
ArgsUsage: "", ArgsUsage: "<dumpfile (optional)>",
Flags: flags.Merge(nodeFlags, rpcFlags), Flags: flags.Merge(nodeFlags, rpcFlags),
Description: `The dumpconfig command shows configuration values.`, Description: `Export configuration values in TOML format (to stdout by default).`,
} }
configFileFlag = &cli.StringFlag{ configFileFlag = &cli.StringFlag{

View file

@ -38,14 +38,6 @@ import (
cli "github.com/urfave/cli/v2" cli "github.com/urfave/cli/v2"
) )
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256(nil)
)
var ( var (
snapshotCommand = &cli.Command{ snapshotCommand = &cli.Command{
Name: "snapshot", Name: "snapshot",
@ -308,7 +300,7 @@ func traverseState(ctx *cli.Context) error {
log.Error("Invalid account encountered during traversal", "err", err) log.Error("Invalid account encountered during traversal", "err", err)
return err return err
} }
if acc.Root != emptyRoot { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root) id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root)
storageTrie, err := trie.NewStateTrie(id, triedb) storageTrie, err := trie.NewStateTrie(id, triedb)
if err != nil { if err != nil {
@ -324,7 +316,7 @@ func traverseState(ctx *cli.Context) error {
return storageIter.Err return storageIter.Err
} }
} }
if !bytes.Equal(acc.CodeHash, emptyCode) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {
log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash)) log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash))
return errors.New("missing code") return errors.New("missing code")
@ -423,7 +415,7 @@ func traverseRawState(ctx *cli.Context) error {
log.Error("Invalid account encountered during traversal", "err", err) log.Error("Invalid account encountered during traversal", "err", err)
return errors.New("invalid account") return errors.New("invalid account")
} }
if acc.Root != emptyRoot { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root) id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root)
storageTrie, err := trie.NewStateTrie(id, triedb) storageTrie, err := trie.NewStateTrie(id, triedb)
if err != nil { if err != nil {
@ -461,7 +453,7 @@ func traverseRawState(ctx *cli.Context) error {
return storageIter.Error() return storageIter.Error()
} }
} }
if !bytes.Equal(acc.CodeHash, emptyCode) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) { if !rawdb.HasCode(chaindb, common.BytesToHash(acc.CodeHash)) {
log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey())) log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey()))
return errors.New("missing code") return errors.New("missing code")
@ -536,7 +528,7 @@ func dumpState(ctx *cli.Context) error {
CodeHash: account.CodeHash, CodeHash: account.CodeHash,
SecureKey: accIt.Hash().Bytes(), SecureKey: accIt.Hash().Bytes(),
} }
if !conf.SkipCode && !bytes.Equal(account.CodeHash, emptyCode) { if !conf.SkipCode && !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash)) da.Code = rawdb.ReadCode(db, common.BytesToHash(account.CodeHash))
} }
if !conf.SkipStorage { if !conf.SkipStorage {

View file

@ -17,6 +17,7 @@
package lru package lru
import ( import (
crand "crypto/rand"
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
@ -181,9 +182,9 @@ func BenchmarkLRU(b *testing.B) {
} }
for i := range keys { for i := range keys {
b := make([]byte, 32) b := make([]byte, 32)
rand.Read(b) crand.Read(b)
keys[i] = string(b) keys[i] = string(b)
rand.Read(b) crand.Read(b)
values[i] = b values[i] = b
} }

View file

@ -49,6 +49,17 @@ func NewHexOrDecimal256(x int64) *HexOrDecimal256 {
return &h return &h
} }
// UnmarshalJSON implements json.Unmarshaler.
//
// It is similar to UnmarshalText, but allows parsing real decimals too, not just
// quoted decimal strings.
func (i *HexOrDecimal256) UnmarshalJSON(input []byte) error {
if len(input) > 0 && input[0] == '"' {
input = input[1 : len(input)-1]
}
return i.UnmarshalText(input)
}
// UnmarshalText implements encoding.TextUnmarshaler. // UnmarshalText implements encoding.TextUnmarshaler.
func (i *HexOrDecimal256) UnmarshalText(input []byte) error { func (i *HexOrDecimal256) UnmarshalText(input []byte) error {
bigint, ok := ParseBig256(string(input)) bigint, ok := ParseBig256(string(input))

View file

@ -41,6 +41,17 @@ const (
// HexOrDecimal64 marshals uint64 as hex or decimal. // HexOrDecimal64 marshals uint64 as hex or decimal.
type HexOrDecimal64 uint64 type HexOrDecimal64 uint64
// UnmarshalJSON implements json.Unmarshaler.
//
// It is similar to UnmarshalText, but allows parsing real decimals too, not just
// quoted decimal strings.
func (i *HexOrDecimal64) UnmarshalJSON(input []byte) error {
if len(input) > 0 && input[0] == '"' {
input = input[1 : len(input)-1]
}
return i.UnmarshalText(input)
}
// UnmarshalText implements encoding.TextUnmarshaler. // UnmarshalText implements encoding.TextUnmarshaler.
func (i *HexOrDecimal64) UnmarshalText(input []byte) error { func (i *HexOrDecimal64) UnmarshalText(input []byte) error {
int, ok := ParseUint64(string(input)) int, ok := ParseUint64(string(input))

View file

@ -56,7 +56,6 @@ func testSetIndex(a interface{}, i int) {
} }
func TestLazyQueue(t *testing.T) { func TestLazyQueue(t *testing.T) {
rand.Seed(time.Now().UnixNano())
clock := &mclock.Simulated{} clock := &mclock.Simulated{}
q := NewLazyQueue(testSetIndex, testPriority, testMaxPriority, clock, testQueueRefresh) q := NewLazyQueue(testSetIndex, testPriority, testMaxPriority, clock, testQueueRefresh)

View file

@ -709,11 +709,11 @@ func TestConcurrentDiskCacheGeneration(t *testing.T) {
block := types.NewBlockWithHeader(&types.Header{ block := types.NewBlockWithHeader(&types.Header{
Number: big.NewInt(3311058), Number: big.NewInt(3311058),
ParentHash: common.HexToHash("0xd783efa4d392943503f28438ad5830b2d5964696ffc285f338585e9fe0a37a05"), ParentHash: common.HexToHash("0xd783efa4d392943503f28438ad5830b2d5964696ffc285f338585e9fe0a37a05"),
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"), UncleHash: types.EmptyUncleHash,
Coinbase: common.HexToAddress("0xc0ea08a2d404d3172d2add29a45be56da40e2949"), Coinbase: common.HexToAddress("0xc0ea08a2d404d3172d2add29a45be56da40e2949"),
Root: common.HexToHash("0x77d14e10470b5850332524f8cd6f69ad21f070ce92dca33ab2858300242ef2f1"), Root: common.HexToHash("0x77d14e10470b5850332524f8cd6f69ad21f070ce92dca33ab2858300242ef2f1"),
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), TxHash: types.EmptyTxsHash,
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"), ReceiptHash: types.EmptyReceiptsHash,
Difficulty: big.NewInt(167925187834220), Difficulty: big.NewInt(167925187834220),
GasLimit: 4015682, GasLimit: 4015682,
GasUsed: 0, GasUsed: 0,

View file

@ -17,6 +17,7 @@
package ethash package ethash
import ( import (
crand "crypto/rand"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"math/big" "math/big"
@ -90,16 +91,15 @@ func TestCalcDifficulty(t *testing.T) {
func randSlice(min, max uint32) []byte { func randSlice(min, max uint32) []byte {
var b = make([]byte, 4) var b = make([]byte, 4)
rand.Read(b) crand.Read(b)
a := binary.LittleEndian.Uint32(b) a := binary.LittleEndian.Uint32(b)
size := min + a%(max-min) size := min + a%(max-min)
out := make([]byte, size) out := make([]byte, size)
rand.Read(out) crand.Read(out)
return out return out
} }
func TestDifficultyCalculators(t *testing.T) { func TestDifficultyCalculators(t *testing.T) {
rand.Seed(2)
for i := 0; i < 5000; i++ { for i := 0; i < 5000; i++ {
// 1 to 300 seconds diff // 1 to 300 seconds diff
var timeDelta = uint64(1 + rand.Uint32()%3000) var timeDelta = uint64(1 + rand.Uint32()%3000)

View file

@ -252,8 +252,8 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
ParentHash: hash, ParentHash: hash,
Difficulty: big.NewInt(1), Difficulty: big.NewInt(1),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
} }
hash = header.Hash() hash = header.Hash()

View file

@ -76,6 +76,9 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash { if hash := types.DeriveSha(block.Withdrawals(), trie.NewStackTrie(nil)); hash != *header.WithdrawalsHash {
return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash) return fmt.Errorf("withdrawals root hash mismatch (header value %x, calculated %x)", *header.WithdrawalsHash, hash)
} }
} else if block.Withdrawals() != nil {
// Withdrawals are not allowed prior to shanghai fork
return fmt.Errorf("withdrawals present in block body")
} }
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {

View file

@ -1318,7 +1318,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
if stats.ignored > 0 { if stats.ignored > 0 {
context = append(context, []interface{}{"ignored", stats.ignored}...) context = append(context, []interface{}{"ignored", stats.ignored}...)
} }
log.Info("Imported new block receipts", context...) log.Debug("Imported new block receipts", context...)
return 0, nil return 0, nil
} }

View file

@ -18,6 +18,7 @@ package bloombits
import ( import (
"bytes" "bytes"
crand "crypto/rand"
"math/rand" "math/rand"
"testing" "testing"
@ -78,7 +79,7 @@ func BenchmarkGenerator(b *testing.B) {
} }
}) })
for i := 0; i < types.BloomBitLength; i++ { for i := 0; i < types.BloomBitLength; i++ {
rand.Read(input[i][:]) crand.Read(input[i][:])
} }
b.Run("random", func(b *testing.B) { b.Run("random", func(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()

View file

@ -138,7 +138,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
// flush is very similar with deriveHash, but the main difference is // flush is very similar with deriveHash, but the main difference is
// all the generated states will be persisted into the given database. // all the generated states will be persisted into the given database.
// Also, the genesis state specification will be flushed as well. // Also, the genesis state specification will be flushed as well.
func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database) error { func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
statedb, err := state.New(common.Hash{}, state.NewDatabaseWithNodeDB(db, triedb), nil) statedb, err := state.New(common.Hash{}, state.NewDatabaseWithNodeDB(db, triedb), nil)
if err != nil { if err != nil {
return err return err
@ -166,15 +166,15 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database) error {
if err != nil { if err != nil {
return err return err
} }
rawdb.WriteGenesisStateSpec(db, root, blob) rawdb.WriteGenesisStateSpec(db, blockhash, blob)
return nil return nil
} }
// CommitGenesisState loads the stored genesis state with the given block // CommitGenesisState loads the stored genesis state with the given block
// hash and commits it into the provided trie database. // hash and commits it into the provided trie database.
func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Hash) error { func CommitGenesisState(db ethdb.Database, triedb *trie.Database, blockhash common.Hash) error {
var alloc GenesisAlloc var alloc GenesisAlloc
blob := rawdb.ReadGenesisStateSpec(db, hash) blob := rawdb.ReadGenesisStateSpec(db, blockhash)
if len(blob) != 0 { if len(blob) != 0 {
if err := alloc.UnmarshalJSON(blob); err != nil { if err := alloc.UnmarshalJSON(blob); err != nil {
return err return err
@ -186,7 +186,7 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Ha
// - supported networks(mainnet, testnets), recover with defined allocations // - supported networks(mainnet, testnets), recover with defined allocations
// - private network, can't recover // - private network, can't recover
var genesis *Genesis var genesis *Genesis
switch hash { switch blockhash {
case params.MainnetGenesisHash: case params.MainnetGenesisHash:
genesis = DefaultGenesisBlock() genesis = DefaultGenesisBlock()
case params.RinkebyGenesisHash: case params.RinkebyGenesisHash:
@ -202,7 +202,7 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Ha
return errors.New("not found") return errors.New("not found")
} }
} }
return alloc.flush(db, triedb) return alloc.flush(db, triedb, blockhash)
} }
// GenesisAccount is an account in the state of the genesis block. // GenesisAccount is an account in the state of the genesis block.
@ -317,7 +317,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *trie.Database, gen
// We have the genesis block in database(perhaps in ancient database) // We have the genesis block in database(perhaps in ancient database)
// but the corresponding state is missing. // but the corresponding state is missing.
header := rawdb.ReadHeader(db, stored, 0) header := rawdb.ReadHeader(db, stored, 0)
if _, err := state.New(header.Root, state.NewDatabaseWithNodeDB(db, triedb), nil); err != nil { if header.Root != types.EmptyRootHash && !rawdb.HasLegacyTrieNode(db, header.Root) {
if genesis == nil { if genesis == nil {
genesis = DefaultGenesisBlock() genesis = DefaultGenesisBlock()
} }
@ -467,7 +467,7 @@ func (g *Genesis) ToBlock() *types.Block {
} }
var withdrawals []*types.Withdrawal var withdrawals []*types.Withdrawal
if g.Config != nil && g.Config.IsShanghai(g.Timestamp) { if g.Config != nil && g.Config.IsShanghai(g.Timestamp) {
head.WithdrawalsHash = &types.EmptyRootHash head.WithdrawalsHash = &types.EmptyWithdrawalsHash
withdrawals = make([]*types.Withdrawal, 0) withdrawals = make([]*types.Withdrawal, 0)
} }
return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals) return types.NewBlock(head, nil, nil, nil, trie.NewStackTrie(nil)).WithWithdrawals(withdrawals)
@ -493,7 +493,7 @@ func (g *Genesis) Commit(db ethdb.Database, triedb *trie.Database) (*types.Block
// All the checks has passed, flush the states derived from the genesis // All the checks has passed, flush the states derived from the genesis
// specification as well as the specification itself into the provided // specification as well as the specification itself into the provided
// database. // database.
if err := g.Alloc.flush(db, triedb); err != nil { if err := g.Alloc.flush(db, triedb, block.Hash()); err != nil {
return nil, err return nil, err
} }
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())

View file

@ -389,7 +389,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time,
if res.ignored > 0 { if res.ignored > 0 {
context = append(context, []interface{}{"ignored", res.ignored}...) context = append(context, []interface{}{"ignored", res.ignored}...)
} }
log.Info("Imported new block headers", context...) log.Debug("Imported new block headers", context...)
return res.status, err return res.status, err
} }

View file

@ -37,7 +37,7 @@ import (
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash { func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
var data []byte var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
data, _ = reader.Ancient(chainFreezerHashTable, number) data, _ = reader.Ancient(ChainFreezerHashTable, number)
if len(data) == 0 { if len(data) == 0 {
// Get it by hash from leveldb // Get it by hash from leveldb
data, _ = db.Get(headerHashKey(number)) data, _ = db.Get(headerHashKey(number))
@ -334,7 +334,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
} }
// read remaining from ancients // read remaining from ancients
max := count * 700 max := count * 700
data, err := db.AncientRange(chainFreezerHeaderTable, i+1-count, count, max) data, err := db.AncientRange(ChainFreezerHeaderTable, i+1-count, count, max)
if err == nil && uint64(len(data)) == count { if err == nil && uint64(len(data)) == count {
// the data is on the order [h, h+1, .., n] -- reordering needed // the data is on the order [h, h+1, .., n] -- reordering needed
for i := range data { for i := range data {
@ -351,7 +351,7 @@ func ReadHeaderRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValu
// First try to look up the data in ancient database. Extra hash // First try to look up the data in ancient database. Extra hash
// comparison is necessary since ancient database only maintains // comparison is necessary since ancient database only maintains
// the canonical data. // the canonical data.
data, _ = reader.Ancient(chainFreezerHeaderTable, number) data, _ = reader.Ancient(ChainFreezerHeaderTable, number)
if len(data) > 0 && crypto.Keccak256Hash(data) == hash { if len(data) > 0 && crypto.Keccak256Hash(data) == hash {
return nil return nil
} }
@ -427,7 +427,7 @@ func deleteHeaderWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number
// isCanon is an internal utility method, to check whether the given number/hash // isCanon is an internal utility method, to check whether the given number/hash
// is part of the ancient (canon) set. // is part of the ancient (canon) set.
func isCanon(reader ethdb.AncientReaderOp, number uint64, hash common.Hash) bool { func isCanon(reader ethdb.AncientReaderOp, number uint64, hash common.Hash) bool {
h, err := reader.Ancient(chainFreezerHashTable, number) h, err := reader.Ancient(ChainFreezerHashTable, number)
if err != nil { if err != nil {
return false return false
} }
@ -443,7 +443,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
// Check if the data is in ancients // Check if the data is in ancients
if isCanon(reader, number, hash) { if isCanon(reader, number, hash) {
data, _ = reader.Ancient(chainFreezerBodiesTable, number) data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
return nil return nil
} }
// If not, try reading from leveldb // If not, try reading from leveldb
@ -458,7 +458,7 @@ func ReadBodyRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue
func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue { func ReadCanonicalBodyRLP(db ethdb.Reader, number uint64) rlp.RawValue {
var data []byte var data []byte
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
data, _ = reader.Ancient(chainFreezerBodiesTable, number) data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
if len(data) > 0 { if len(data) > 0 {
return nil return nil
} }
@ -526,7 +526,7 @@ func ReadTdRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
// Check if the data is in ancients // Check if the data is in ancients
if isCanon(reader, number, hash) { if isCanon(reader, number, hash) {
data, _ = reader.Ancient(chainFreezerDifficultyTable, number) data, _ = reader.Ancient(ChainFreezerDifficultyTable, number)
return nil return nil
} }
// If not, try reading from leveldb // If not, try reading from leveldb
@ -586,7 +586,7 @@ func ReadReceiptsRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawVa
db.ReadAncients(func(reader ethdb.AncientReaderOp) error { db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
// Check if the data is in ancients // Check if the data is in ancients
if isCanon(reader, number, hash) { if isCanon(reader, number, hash) {
data, _ = reader.Ancient(chainFreezerReceiptTable, number) data, _ = reader.Ancient(ChainFreezerReceiptTable, number)
return nil return nil
} }
// If not, try reading from leveldb // If not, try reading from leveldb
@ -787,19 +787,19 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage, td *big.Int) error { func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts []*types.ReceiptForStorage, td *big.Int) error {
num := block.NumberU64() num := block.NumberU64()
if err := op.AppendRaw(chainFreezerHashTable, num, block.Hash().Bytes()); err != nil { if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
return fmt.Errorf("can't add block %d hash: %v", num, err) return fmt.Errorf("can't add block %d hash: %v", num, err)
} }
if err := op.Append(chainFreezerHeaderTable, num, header); err != nil { if err := op.Append(ChainFreezerHeaderTable, num, header); err != nil {
return fmt.Errorf("can't append block header %d: %v", num, err) return fmt.Errorf("can't append block header %d: %v", num, err)
} }
if err := op.Append(chainFreezerBodiesTable, num, block.Body()); err != nil { if err := op.Append(ChainFreezerBodiesTable, num, block.Body()); err != nil {
return fmt.Errorf("can't append block body %d: %v", num, err) return fmt.Errorf("can't append block body %d: %v", num, err)
} }
if err := op.Append(chainFreezerReceiptTable, num, receipts); err != nil { if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil {
return fmt.Errorf("can't append block %d receipts: %v", num, err) return fmt.Errorf("can't append block %d receipts: %v", num, err)
} }
if err := op.Append(chainFreezerDifficultyTable, num, td); err != nil { if err := op.Append(ChainFreezerDifficultyTable, num, td); err != nil {
return fmt.Errorf("can't append block %d total difficulty: %v", num, err) return fmt.Errorf("can't append block %d total difficulty: %v", num, err)
} }
return nil return nil

View file

@ -113,8 +113,8 @@ func TestBlockStorage(t *testing.T) {
block := types.NewBlockWithHeader(&types.Header{ block := types.NewBlockWithHeader(&types.Header{
Extra: []byte("test block"), Extra: []byte("test block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
}) })
if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil { if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
t.Fatalf("Non existent block returned: %v", entry) t.Fatalf("Non existent block returned: %v", entry)
@ -161,8 +161,8 @@ func TestPartialBlockStorage(t *testing.T) {
block := types.NewBlockWithHeader(&types.Header{ block := types.NewBlockWithHeader(&types.Header{
Extra: []byte("test block"), Extra: []byte("test block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
}) })
// Store a header and check that it's not recognized as a block // Store a header and check that it's not recognized as a block
WriteHeader(db, block.Header()) WriteHeader(db, block.Header())
@ -198,8 +198,8 @@ func TestBadBlockStorage(t *testing.T) {
Number: big.NewInt(1), Number: big.NewInt(1),
Extra: []byte("bad block"), Extra: []byte("bad block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
}) })
if entry := ReadBadBlock(db, block.Hash()); entry != nil { if entry := ReadBadBlock(db, block.Hash()); entry != nil {
t.Fatalf("Non existent block returned: %v", entry) t.Fatalf("Non existent block returned: %v", entry)
@ -216,8 +216,8 @@ func TestBadBlockStorage(t *testing.T) {
Number: big.NewInt(2), Number: big.NewInt(2),
Extra: []byte("bad block two"), Extra: []byte("bad block two"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
}) })
WriteBadBlock(db, blockTwo) WriteBadBlock(db, blockTwo)
@ -235,8 +235,8 @@ func TestBadBlockStorage(t *testing.T) {
Number: big.NewInt(int64(n)), Number: big.NewInt(int64(n)),
Extra: []byte("bad block"), Extra: []byte("bad block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
}) })
WriteBadBlock(db, block) WriteBadBlock(db, block)
} }
@ -446,8 +446,8 @@ func TestAncientStorage(t *testing.T) {
Number: big.NewInt(0), Number: big.NewInt(0),
Extra: []byte("test block"), Extra: []byte("test block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
}) })
// Ensure nothing non-existent will be read // Ensure nothing non-existent will be read
hash, number := block.Hash(), block.NumberU64() hash, number := block.Hash(), block.NumberU64()
@ -889,8 +889,8 @@ func TestHeadersRLPStorage(t *testing.T) {
Number: big.NewInt(int64(i)), Number: big.NewInt(int64(i)),
Extra: []byte("test block"), Extra: []byte("test block"),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
ParentHash: pHash, ParentHash: pHash,
}) })
chain = append(chain, block) chain = append(chain, block)

View file

@ -82,15 +82,15 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
} }
// ReadGenesisStateSpec retrieves the genesis state specification based on the // ReadGenesisStateSpec retrieves the genesis state specification based on the
// given genesis hash. // given genesis (block-)hash.
func ReadGenesisStateSpec(db ethdb.KeyValueReader, hash common.Hash) []byte { func ReadGenesisStateSpec(db ethdb.KeyValueReader, blockhash common.Hash) []byte {
data, _ := db.Get(genesisStateSpecKey(hash)) data, _ := db.Get(genesisStateSpecKey(blockhash))
return data return data
} }
// WriteGenesisStateSpec writes the genesis state specification into the disk. // WriteGenesisStateSpec writes the genesis state specification into the disk.
func WriteGenesisStateSpec(db ethdb.KeyValueWriter, hash common.Hash, data []byte) { func WriteGenesisStateSpec(db ethdb.KeyValueWriter, blockhash common.Hash, data []byte) {
if err := db.Put(genesisStateSpecKey(hash), data); err != nil { if err := db.Put(genesisStateSpecKey(blockhash), data); err != nil {
log.Crit("Failed to store genesis state", "err", err) log.Crit("Failed to store genesis state", "err", err)
} }
} }

View file

@ -18,30 +18,30 @@ package rawdb
// The list of table names of chain freezer. // The list of table names of chain freezer.
const ( const (
// chainFreezerHeaderTable indicates the name of the freezer header table. // ChainFreezerHeaderTable indicates the name of the freezer header table.
chainFreezerHeaderTable = "headers" ChainFreezerHeaderTable = "headers"
// chainFreezerHashTable indicates the name of the freezer canonical hash table. // ChainFreezerHashTable indicates the name of the freezer canonical hash table.
chainFreezerHashTable = "hashes" ChainFreezerHashTable = "hashes"
// chainFreezerBodiesTable indicates the name of the freezer block body table. // ChainFreezerBodiesTable indicates the name of the freezer block body table.
chainFreezerBodiesTable = "bodies" ChainFreezerBodiesTable = "bodies"
// chainFreezerReceiptTable indicates the name of the freezer receipts table. // ChainFreezerReceiptTable indicates the name of the freezer receipts table.
chainFreezerReceiptTable = "receipts" ChainFreezerReceiptTable = "receipts"
// chainFreezerDifficultyTable indicates the name of the freezer total difficulty table. // ChainFreezerDifficultyTable indicates the name of the freezer total difficulty table.
chainFreezerDifficultyTable = "diffs" ChainFreezerDifficultyTable = "diffs"
) )
// chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables. // chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables.
// Hashes and difficulties don't compress well. // Hashes and difficulties don't compress well.
var chainFreezerNoSnappy = map[string]bool{ var chainFreezerNoSnappy = map[string]bool{
chainFreezerHeaderTable: false, ChainFreezerHeaderTable: false,
chainFreezerHashTable: true, ChainFreezerHashTable: true,
chainFreezerBodiesTable: false, ChainFreezerBodiesTable: false,
chainFreezerReceiptTable: false, ChainFreezerReceiptTable: false,
chainFreezerDifficultyTable: true, ChainFreezerDifficultyTable: true,
} }
// The list of identifiers of ancient stores. // The list of identifiers of ancient stores.

View file

@ -55,8 +55,8 @@ type chainFreezer struct {
} }
// newChainFreezer initializes the freezer for ancient chain data. // newChainFreezer initializes the freezer for ancient chain data.
func newChainFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*chainFreezer, error) { func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFreezer, error) {
freezer, err := NewFreezer(datadir, namespace, readonly, maxTableSize, tables) freezer, err := NewChainFreezer(datadir, namespace, readonly)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -280,19 +280,19 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
} }
// Write to the batch. // Write to the batch.
if err := op.AppendRaw(chainFreezerHashTable, number, hash[:]); err != nil { if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil {
return fmt.Errorf("can't write hash to Freezer: %v", err) return fmt.Errorf("can't write hash to Freezer: %v", err)
} }
if err := op.AppendRaw(chainFreezerHeaderTable, number, header); err != nil { if err := op.AppendRaw(ChainFreezerHeaderTable, number, header); err != nil {
return fmt.Errorf("can't write header to Freezer: %v", err) return fmt.Errorf("can't write header to Freezer: %v", err)
} }
if err := op.AppendRaw(chainFreezerBodiesTable, number, body); err != nil { if err := op.AppendRaw(ChainFreezerBodiesTable, number, body); err != nil {
return fmt.Errorf("can't write body to Freezer: %v", err) return fmt.Errorf("can't write body to Freezer: %v", err)
} }
if err := op.AppendRaw(chainFreezerReceiptTable, number, receipts); err != nil { if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil {
return fmt.Errorf("can't write receipts to Freezer: %v", err) return fmt.Errorf("can't write receipts to Freezer: %v", err)
} }
if err := op.AppendRaw(chainFreezerDifficultyTable, number, td); err != nil { if err := op.AppendRaw(ChainFreezerDifficultyTable, number, td); err != nil {
return fmt.Errorf("can't write td to Freezer: %v", err) return fmt.Errorf("can't write td to Freezer: %v", err)
} }

View file

@ -50,7 +50,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
if i+count > frozen { if i+count > frozen {
count = frozen - i count = frozen - i
} }
data, err := db.AncientRange(chainFreezerHashTable, i, count, 32*count) data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count)
if err != nil { if err != nil {
log.Crit("Failed to init database from freezer", "err", err) log.Crit("Failed to init database from freezer", "err", err)
} }

View file

@ -200,7 +200,7 @@ func resolveChainFreezerDir(ancient string) string {
// where the chain freezer can be opened. // where the chain freezer can be opened.
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly, ancientPrune bool) (ethdb.Database, error) { func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly, ancientPrune bool) (ethdb.Database, error) {
// Create the idle freezer instance // Create the idle freezer instance
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, freezerTableSize, chainFreezerNoSnappy) frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -232,7 +232,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
// If the freezer already contains something, ensure that the genesis blocks // If the freezer already contains something, ensure that the genesis blocks
// match, otherwise we might mix up freezers across chains and destroy both // match, otherwise we might mix up freezers across chains and destroy both
// the freezer and the key-value store. // the freezer and the key-value store.
frgenesis, err := frdb.Ancient(chainFreezerHashTable, 0) frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err) return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
} else if !bytes.Equal(kvgenesis, frgenesis) { } else if !bytes.Equal(kvgenesis, frgenesis) {

View file

@ -79,6 +79,12 @@ type Freezer struct {
closeOnce sync.Once closeOnce sync.Once
} }
// NewChainFreezer is a small utility method around NewFreezer that sets the
// default parameters for the chain storage.
func NewChainFreezer(datadir string, namespace string, readonly bool) (*Freezer, error) {
return NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
}
// NewFreezer creates a freezer instance for maintaining immutable ordered // NewFreezer creates a freezer instance for maintaining immutable ordered
// data according to the given parameters. // data according to the given parameters.
// //

View file

@ -27,17 +27,12 @@ import (
"sync/atomic" "sync/atomic"
"testing" "testing"
"testing/quick" "testing/quick"
"time"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func init() {
rand.Seed(time.Now().Unix())
}
// TestFreezerBasics test initializing a freezertable from scratch, writing to the table, // TestFreezerBasics test initializing a freezertable from scratch, writing to the table,
// and reading it back. // and reading it back.
func TestFreezerBasics(t *testing.T) { func TestFreezerBasics(t *testing.T) {

View file

@ -117,7 +117,7 @@ func (it *NodeIterator) step() error {
if !it.dataIt.Next(true) { if !it.dataIt.Next(true) {
it.dataIt = nil it.dataIt = nil
} }
if !bytes.Equal(account.CodeHash, emptyCodeHash) { if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
it.codeHash = common.BytesToHash(account.CodeHash) it.codeHash = common.BytesToHash(account.CodeHash)
addrHash := common.BytesToHash(it.stateIt.LeafKey()) addrHash := common.BytesToHash(it.stateIt.LeafKey())
it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash)) it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash))

View file

@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/state/snapshot"
"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/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -55,14 +54,6 @@ const (
rangeCompactionThreshold = 100000 rangeCompactionThreshold = 100000
) )
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256(nil)
)
// Config includes all the configurations for pruning. // Config includes all the configurations for pruning.
type Config struct { type Config struct {
Datadir string // The directory of the state database Datadir string // The directory of the state database
@ -446,7 +437,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
if err := rlp.DecodeBytes(accIter.LeafBlob(), &acc); err != nil { if err := rlp.DecodeBytes(accIter.LeafBlob(), &acc); err != nil {
return err return err
} }
if acc.Root != emptyRoot { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root) id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root)
storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db)) storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db))
if err != nil { if err != nil {
@ -463,7 +454,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
return storageIter.Error() return storageIter.Error()
} }
} }
if !bytes.Equal(acc.CodeHash, emptyCode) { if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
stateBloom.Put(acc.CodeHash, nil) stateBloom.Put(acc.CodeHash, nil)
} }
} }

View file

@ -21,6 +21,7 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -41,10 +42,10 @@ func SlimAccount(nonce uint64, balance *big.Int, root common.Hash, codehash []by
Nonce: nonce, Nonce: nonce,
Balance: balance, Balance: balance,
} }
if root != emptyRoot { if root != types.EmptyRootHash {
slim.Root = root[:] slim.Root = root[:]
} }
if !bytes.Equal(codehash, emptyCode[:]) { if !bytes.Equal(codehash, types.EmptyCodeHash[:]) {
slim.CodeHash = codehash slim.CodeHash = codehash
} }
return slim return slim
@ -68,10 +69,10 @@ func FullAccount(data []byte) (Account, error) {
return Account{}, err return Account{}, err
} }
if len(account.Root) == 0 { if len(account.Root) == 0 {
account.Root = emptyRoot[:] account.Root = types.EmptyRootHash[:]
} }
if len(account.CodeHash) == 0 { if len(account.CodeHash) == 0 {
account.CodeHash = emptyCode[:] account.CodeHash = types.EmptyCodeHash[:]
} }
return account, nil return account, nil
} }

View file

@ -28,6 +28,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/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -74,7 +75,7 @@ func GenerateTrie(snaptree *Tree, root common.Hash, src ethdb.Database, dst ethd
scheme := snaptree.triedb.Scheme() scheme := snaptree.triedb.Scheme()
got, err := generateTrieRoot(dst, scheme, acctIt, common.Hash{}, stackTrieGenerate, func(dst ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) { got, err := generateTrieRoot(dst, scheme, acctIt, common.Hash{}, stackTrieGenerate, func(dst ethdb.KeyValueWriter, accountHash, codeHash common.Hash, stat *generateStats) (common.Hash, error) {
// Migrate the code first, commit the contract code into the tmp db. // Migrate the code first, commit the contract code into the tmp db.
if codeHash != emptyCode { if codeHash != types.EmptyCodeHash {
code := rawdb.ReadCode(src, codeHash) code := rawdb.ReadCode(src, codeHash)
if len(code) == 0 { if len(code) == 0 {
return common.Hash{}, errors.New("failed to read contract code") return common.Hash{}, errors.New("failed to read contract code")

View file

@ -18,6 +18,7 @@ package snapshot
import ( import (
"bytes" "bytes"
crand "crypto/rand"
"math/rand" "math/rand"
"testing" "testing"
@ -73,7 +74,7 @@ func TestMergeBasics(t *testing.T) {
if rand.Intn(2) == 0 { if rand.Intn(2) == 0 {
accStorage := make(map[common.Hash][]byte) accStorage := make(map[common.Hash][]byte)
value := make([]byte, 32) value := make([]byte, 32)
rand.Read(value) crand.Read(value)
accStorage[randomHash()] = value accStorage[randomHash()] = value
storage[h] = accStorage storage[h] = accStorage
} }
@ -294,7 +295,7 @@ func BenchmarkSearchSlot(b *testing.B) {
accStorage := make(map[common.Hash][]byte) accStorage := make(map[common.Hash][]byte)
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
value := make([]byte, 32) value := make([]byte, 32)
rand.Read(value) crand.Read(value)
accStorage[randomHash()] = value accStorage[randomHash()] = value
storage[accountKey] = accStorage storage[accountKey] = accStorage
} }
@ -330,7 +331,7 @@ func BenchmarkFlatten(b *testing.B) {
accStorage := make(map[common.Hash][]byte) accStorage := make(map[common.Hash][]byte)
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
value := make([]byte, 32) value := make([]byte, 32)
rand.Read(value) crand.Read(value)
accStorage[randomHash()] = value accStorage[randomHash()] = value
} }
storage[accountKey] = accStorage storage[accountKey] = accStorage
@ -379,7 +380,7 @@ func BenchmarkJournal(b *testing.B) {
accStorage := make(map[common.Hash][]byte) accStorage := make(map[common.Hash][]byte)
for i := 0; i < 200; i++ { for i := 0; i < 200; i++ {
value := make([]byte, 32) value := make([]byte, 32)
rand.Read(value) crand.Read(value)
accStorage[randomHash()] = value accStorage[randomHash()] = value
} }
storage[accountKey] = accStorage storage[accountKey] = accStorage

View file

@ -27,7 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/core/types"
"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/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -35,12 +35,6 @@ import (
) )
var ( var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256Hash(nil)
// accountCheckRange is the upper limit of the number of accounts involved in // accountCheckRange is the upper limit of the number of accounts involved in
// each range check. This is a value estimated based on experience. If this // each range check. This is a value estimated based on experience. If this
// range is too large, the failure rate of range proof will increase. Otherwise, // range is too large, the failure rate of range proof will increase. Otherwise,
@ -591,10 +585,10 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er
if accMarker == nil || !bytes.Equal(account[:], accMarker) { if accMarker == nil || !bytes.Equal(account[:], accMarker) {
dataLen := len(val) // Approximate size, saves us a round of RLP-encoding dataLen := len(val) // Approximate size, saves us a round of RLP-encoding
if !write { if !write {
if bytes.Equal(acc.CodeHash, emptyCode[:]) { if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) {
dataLen -= 32 dataLen -= 32
} }
if acc.Root == emptyRoot { if acc.Root == types.EmptyRootHash {
dataLen -= 32 dataLen -= 32
} }
snapRecoveredAccountMeter.Mark(1) snapRecoveredAccountMeter.Mark(1)
@ -621,7 +615,7 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er
// If the iterated account is the contract, create a further loop to // If the iterated account is the contract, create a further loop to
// verify or regenerate the contract storage. // verify or regenerate the contract storage.
if acc.Root == emptyRoot { if acc.Root == types.EmptyRootHash {
ctx.removeStorageAt(account) ctx.removeStorageAt(account)
} else { } else {
var storeMarker []byte var storeMarker []byte

View file

@ -25,6 +25,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/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -49,9 +50,9 @@ func TestGeneration(t *testing.T) {
var helper = newHelper() var helper = newHelper()
stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false) stRoot := helper.makeStorageTrie(common.Hash{}, common.Hash{}, []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, false)
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
@ -83,16 +84,16 @@ func TestGenerateExistentState(t *testing.T) {
var helper = newHelper() var helper = newHelper()
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addSnapAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
root, snap := helper.CommitAndGenerate() root, snap := helper.CommitAndGenerate()
@ -235,28 +236,28 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
helper := newHelper() helper := newHelper()
// Account one, empty root but non-empty database // Account one, empty root but non-empty database
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
// Account two, non empty root but empty database // Account two, non empty root but empty database
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-2")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
// Miss slots // Miss slots
{ {
// Account three, non empty root but misses slots in the beginning // Account three, non empty root but misses slots in the beginning
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-2", "key-3"}, []string{"val-2", "val-3"})
// Account four, non empty root but misses slots in the middle // Account four, non empty root but misses slots in the middle
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-4")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"}) helper.addSnapStorage("acc-4", []string{"key-1", "key-3"}, []string{"val-1", "val-3"})
// Account five, non empty root but misses slots in the end // Account five, non empty root but misses slots in the end
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-5")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-5", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"}) helper.addSnapStorage("acc-5", []string{"key-1", "key-2"}, []string{"val-1", "val-2"})
} }
@ -264,22 +265,22 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
{ {
// Account six, non empty root but wrong slots in the beginning // Account six, non empty root but wrong slots in the beginning
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-6")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"}) helper.addSnapStorage("acc-6", []string{"key-1", "key-2", "key-3"}, []string{"badval-1", "val-2", "val-3"})
// Account seven, non empty root but wrong slots in the middle // Account seven, non empty root but wrong slots in the middle
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-7")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-7", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"}) helper.addSnapStorage("acc-7", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "badval-2", "val-3"})
// Account eight, non empty root but wrong slots in the end // Account eight, non empty root but wrong slots in the end
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-8")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-8", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"}) helper.addSnapStorage("acc-8", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "badval-3"})
// Account 9, non empty root but rotated slots // Account 9, non empty root but rotated slots
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-9")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-9", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"}) helper.addSnapStorage("acc-9", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-3", "val-2"})
} }
@ -287,17 +288,17 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
{ {
// Account 10, non empty root but extra slots in the beginning // Account 10, non empty root but extra slots in the beginning
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-10")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-10", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-10", []string{"key-0", "key-1", "key-2", "key-3"}, []string{"val-0", "val-1", "val-2", "val-3"})
// Account 11, non empty root but extra slots in the middle // Account 11, non empty root but extra slots in the middle
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-11")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-11", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"}) helper.addSnapStorage("acc-11", []string{"key-1", "key-2", "key-2-1", "key-3"}, []string{"val-1", "val-2", "val-2-1", "val-3"})
// Account 12, non empty root but extra slots in the end // Account 12, non empty root but extra slots in the end
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-12")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-12", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"}) helper.addSnapStorage("acc-12", []string{"key-1", "key-2", "key-3", "key-4"}, []string{"val-1", "val-2", "val-3", "val-4"})
} }
@ -337,25 +338,25 @@ func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
// Missing accounts, only in the trie // Missing accounts, only in the trie
{ {
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Beginning
helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // Middle
helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
} }
// Wrong accounts // Wrong accounts
{ {
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")}) helper.addSnapAccount("acc-2", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: common.Hex2Bytes("0x1234")})
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
} }
// Extra accounts, only in the snap // Extra accounts, only in the snap
{ {
helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyRoot.Bytes()}) // before the beginning helper.addSnapAccount("acc-0", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // before the beginning
helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle helper.addSnapAccount("acc-5", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle
helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyRoot.Bytes()}) // after the end helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
} }
root, snap := helper.CommitAndGenerate() root, snap := helper.CommitAndGenerate()
@ -384,9 +385,9 @@ func TestGenerateCorruptAccountTrie(t *testing.T) {
// without any storage slots to keep the test smaller. // without any storage slots to keep the test smaller.
helper := newHelper() helper := newHelper()
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074 helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978 root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
@ -419,10 +420,10 @@ func TestGenerateMissingStorageTrie(t *testing.T) {
helper := newHelper() helper := newHelper()
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit() root := helper.Commit()
@ -453,10 +454,10 @@ func TestGenerateCorruptStorageTrie(t *testing.T) {
helper := newHelper() helper := newHelper()
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67 stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) // 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7 helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot = helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2 helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
root := helper.Commit() root := helper.Commit()
@ -488,7 +489,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"}, []string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true, true,
) )
acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@ -508,7 +509,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) {
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"}, []string{"val-1", "val-2", "val-3", "val-4", "val-5"},
true, true,
) )
acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte("acc-2")) key := hashData([]byte("acc-2"))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val) rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@ -559,7 +560,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) {
[]string{"val-1", "val-2", "val-3"}, []string{"val-1", "val-2", "val-3"},
true, true,
) )
acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()} acc := &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
@ -573,8 +574,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) {
{ {
// 100 accounts exist only in snapshot // 100 accounts exist only in snapshot
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
//acc := &Account{Balance: big.NewInt(int64(i)), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()} acc := &Account{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}
acc := &Account{Balance: big.NewInt(int64(i)), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
key := hashData([]byte(fmt.Sprintf("acc-%d", i))) key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
rawdb.WriteAccountSnapshot(helper.diskdb, key, val) rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
@ -611,7 +611,7 @@ func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
} }
helper := newHelper() helper := newHelper()
{ {
acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} acc := &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val) helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val)
helper.accTrie.Update(common.HexToHash("0x07").Bytes(), val) helper.accTrie.Update(common.HexToHash("0x07").Bytes(), val)
@ -648,7 +648,7 @@ func TestGenerateWithMalformedSnapdata(t *testing.T) {
} }
helper := newHelper() helper := newHelper()
{ {
acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()} acc := &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}
val, _ := rlp.EncodeToBytes(acc) val, _ := rlp.EncodeToBytes(acc)
helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val) helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val)
@ -687,7 +687,7 @@ func TestGenerateFromEmptySnap(t *testing.T) {
for i := 0; i < 400; i++ { for i := 0; i < 400; i++ {
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(fmt.Sprintf("acc-%d", i))), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount(fmt.Sprintf("acc-%d", i), helper.addTrieAccount(fmt.Sprintf("acc-%d", i),
&Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
} }
root, snap := helper.CommitAndGenerate() root, snap := helper.CommitAndGenerate()
t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4 t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
@ -724,7 +724,7 @@ func TestGenerateWithIncompleteStorage(t *testing.T) {
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
accKey := fmt.Sprintf("acc-%d", i) accKey := fmt.Sprintf("acc-%d", i)
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(accKey)), stKeys, stVals, true) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte(accKey)), stKeys, stVals, true)
helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount(accKey, &Account{Balance: big.NewInt(int64(i)), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
var moddedKeys []string var moddedKeys []string
var moddedVals []string var moddedVals []string
for ii := 0; ii < 8; ii++ { for ii := 0; ii < 8; ii++ {
@ -816,11 +816,11 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
var helper = newHelper() var helper = newHelper()
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-1", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}) helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
@ -851,11 +851,11 @@ func TestGenerateBrokenSnapshotWithDanglingStorage(t *testing.T) {
var helper = newHelper() var helper = newHelper()
stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) stRoot := helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-1")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true) helper.makeStorageTrie(common.Hash{}, hashData([]byte("acc-3")), []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"}, true)
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()}) helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()})
populateDangling(helper.diskdb) populateDangling(helper.diskdb)

View file

@ -18,6 +18,7 @@ package snapshot
import ( import (
"bytes" "bytes"
crand "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/rand" "math/rand"
@ -47,7 +48,7 @@ func TestAccountIteratorBasics(t *testing.T) {
if rand.Intn(2) == 0 { if rand.Intn(2) == 0 {
accStorage := make(map[common.Hash][]byte) accStorage := make(map[common.Hash][]byte)
value := make([]byte, 32) value := make([]byte, 32)
rand.Read(value) crand.Read(value)
accStorage[randomHash()] = value accStorage[randomHash()] = value
storage[h] = accStorage storage[h] = accStorage
} }
@ -79,7 +80,7 @@ func TestStorageIteratorBasics(t *testing.T) {
var nilstorage int var nilstorage int
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
rand.Read(value) crand.Read(value)
if rand.Intn(2) == 0 { if rand.Intn(2) == 0 {
accStorage[randomHash()] = common.CopyBytes(value) accStorage[randomHash()] = common.CopyBytes(value)
} else { } else {

View file

@ -17,6 +17,7 @@
package snapshot package snapshot
import ( import (
crand "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/big" "math/big"
@ -27,13 +28,14 @@ import (
"github.com/VictoriaMetrics/fastcache" "github.com/VictoriaMetrics/fastcache"
"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/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
// randomHash generates a random blob of data and returns it as a hash. // randomHash generates a random blob of data and returns it as a hash.
func randomHash() common.Hash { func randomHash() common.Hash {
var hash common.Hash var hash common.Hash
if n, err := rand.Read(hash[:]); n != common.HashLength || err != nil { if n, err := crand.Read(hash[:]); n != common.HashLength || err != nil {
panic(err) panic(err)
} }
return hash return hash
@ -46,7 +48,7 @@ func randomAccount() []byte {
Balance: big.NewInt(rand.Int63()), Balance: big.NewInt(rand.Int63()),
Nonce: rand.Uint64(), Nonce: rand.Uint64(),
Root: root[:], Root: root[:],
CodeHash: emptyCode[:], CodeHash: types.EmptyCodeHash[:],
} }
data, _ := rlp.EncodeToBytes(a) data, _ := rlp.EncodeToBytes(a)
return data return data

View file

@ -31,8 +31,6 @@ import (
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
) )
var emptyCodeHash = crypto.Keccak256(nil)
type Code []byte type Code []byte
func (c Code) String() string { func (c Code) String() string {
@ -95,7 +93,7 @@ type stateObject struct {
// empty returns whether the account is considered empty. // empty returns whether the account is considered empty.
func (s *stateObject) empty() bool { func (s *stateObject) empty() bool {
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes())
} }
// newObject creates a state object. // newObject creates a state object.
@ -104,10 +102,10 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st
data.Balance = new(big.Int) data.Balance = new(big.Int)
} }
if data.CodeHash == nil { if data.CodeHash == nil {
data.CodeHash = emptyCodeHash data.CodeHash = types.EmptyCodeHash.Bytes()
} }
if data.Root == (common.Hash{}) { if data.Root == (common.Hash{}) {
data.Root = emptyRoot data.Root = types.EmptyRootHash
} }
return &stateObject{ return &stateObject{
db: db, db: db,
@ -154,7 +152,7 @@ func (s *stateObject) getTrie(db Database) (Trie, error) {
if s.trie == nil { if s.trie == nil {
// Try fetching from prefetcher first // Try fetching from prefetcher first
// We don't prefetch empty tries // We don't prefetch empty tries
if s.data.Root != emptyRoot && s.db.prefetcher != nil { if s.data.Root != types.EmptyRootHash && s.db.prefetcher != nil {
// When the miner is creating the pending state, there is no // When the miner is creating the pending state, there is no
// prefetcher // prefetcher
s.trie = s.db.prefetcher.trie(s.addrHash, s.data.Root) s.trie = s.db.prefetcher.trie(s.addrHash, s.data.Root)
@ -270,7 +268,7 @@ func (s *stateObject) finalise(prefetch bool) {
slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure slotsToPrefetch = append(slotsToPrefetch, common.CopyBytes(key[:])) // Copy needed for closure
} }
} }
if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != emptyRoot { if s.db.prefetcher != nil && prefetch && len(slotsToPrefetch) > 0 && s.data.Root != types.EmptyRootHash {
s.db.prefetcher.prefetch(s.addrHash, s.data.Root, slotsToPrefetch) s.db.prefetcher.prefetch(s.addrHash, s.data.Root, slotsToPrefetch)
} }
if len(s.dirtyStorage) > 0 { if len(s.dirtyStorage) > 0 {
@ -454,7 +452,7 @@ func (s *stateObject) Code(db Database) []byte {
if s.code != nil { if s.code != nil {
return s.code return s.code
} }
if bytes.Equal(s.CodeHash(), emptyCodeHash) { if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
return nil return nil
} }
code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash())) code, err := db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash()))
@ -472,7 +470,7 @@ func (s *stateObject) CodeSize(db Database) int {
if s.code != nil { if s.code != nil {
return len(s.code) return len(s.code)
} }
if bytes.Equal(s.CodeHash(), emptyCodeHash) { if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
return 0 return 0
} }
size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash())) size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))

View file

@ -41,11 +41,6 @@ type revision struct {
journalIndex int journalIndex int
} }
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
)
type proofList [][]byte type proofList [][]byte
func (n *proofList) Put(key []byte, value []byte) error { func (n *proofList) Put(key []byte, value []byte) error {
@ -580,10 +575,10 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
Root: common.BytesToHash(acc.Root), Root: common.BytesToHash(acc.Root),
} }
if len(data.CodeHash) == 0 { if len(data.CodeHash) == 0 {
data.CodeHash = emptyCodeHash data.CodeHash = types.EmptyCodeHash.Bytes()
} }
if data.Root == (common.Hash{}) { if data.Root == (common.Hash{}) {
data.Root = emptyRoot data.Root = types.EmptyRootHash
} }
} }
} }
@ -1066,11 +1061,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
s.stateObjectsDestruct = make(map[common.Address]struct{}) s.stateObjectsDestruct = make(map[common.Address]struct{})
} }
if root == (common.Hash{}) { if root == (common.Hash{}) {
root = emptyRoot root = types.EmptyRootHash
} }
origin := s.originalRoot origin := s.originalRoot
if origin == (common.Hash{}) { if origin == (common.Hash{}) {
origin = emptyRoot origin = types.EmptyRootHash
} }
if root != origin { if root != origin {
start := time.Now() start := time.Now()
@ -1126,11 +1121,6 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d
s.transientStorage = newTransientStorage() s.transientStorage = newTransientStorage()
} }
func (s *StateDB) SetTxHashAndIndex(txhash common.Hash, ti int) {
s.thash = txhash
s.txIndex = ti
}
// AddAddressToAccessList adds the given address to the access list // AddAddressToAccessList adds the given address to the access list
func (s *StateDB) AddAddressToAccessList(addr common.Address) { func (s *StateDB) AddAddressToAccessList(addr common.Address) {
if s.accessList.AddAddress(addr) { if s.accessList.AddAddress(addr) {

View file

@ -134,8 +134,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
// Tests that an empty state is not scheduled for syncing. // Tests that an empty state is not scheduled for syncing.
func TestEmptyStateSync(t *testing.T) { func TestEmptyStateSync(t *testing.T) {
db := trie.NewDatabase(rawdb.NewMemoryDatabase()) db := trie.NewDatabase(rawdb.NewMemoryDatabase())
empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, db.Scheme())
sync := NewStateSync(empty, rawdb.NewMemoryDatabase(), nil, db.Scheme())
if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 { if paths, nodes, codes := sync.Missing(1); len(paths) != 0 || len(nodes) != 0 || len(codes) != 0 {
t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes) t.Errorf("content requested for empty state: %v, %v, %v", nodes, paths, codes)
} }
@ -555,7 +554,7 @@ func TestIncompleteStateSync(t *testing.T) {
isCode[crypto.Keccak256Hash(acc.code)] = struct{}{} isCode[crypto.Keccak256Hash(acc.code)] = struct{}{}
} }
} }
isCode[common.BytesToHash(emptyCodeHash)] = struct{}{} isCode[types.EmptyCodeHash] = struct{}{}
checkTrieConsistency(db, srcRoot) checkTrieConsistency(db, srcRoot)
// Create a destination state and sync with the scheduler // Create a destination state and sync with the scheduler

View file

@ -95,6 +95,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
} }
receipts = append(receipts, receipt) receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...) allLogs = append(allLogs, receipt.Logs...)
// Finalize trace logger result and save to underlying database if necessary.
switch t := cfg.Tracer.(type) {
case *txtracelib.OeTracer:
log.Debug("Persist oe-style trace result to database", "blockNumber", header.Number.Int64(), "txHash", tx.Hash())
t.PersistTrace()
default:
}
} }
if tracing { if tracing {

View file

@ -404,7 +404,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
header.BaseFee = misc.CalcBaseFee(config, parent.Header()) header.BaseFee = misc.CalcBaseFee(config, parent.Header())
} }
if config.IsShanghai(header.Time) { if config.IsShanghai(header.Time) {
header.WithdrawalsHash = &types.EmptyRootHash header.WithdrawalsHash = &types.EmptyWithdrawalsHash
} }
var receipts []*types.Receipt var receipts []*types.Receipt
// The post-state result doesn't need to be correct (this is a bad block), but we do need something there // The post-state result doesn't need to be correct (this is a bad block), but we do need something there

View file

@ -18,6 +18,7 @@ package txpool
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
crand "crypto/rand"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@ -92,7 +93,7 @@ func pricedTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ec
func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction { func pricedDataTransaction(nonce uint64, gaslimit uint64, gasprice *big.Int, key *ecdsa.PrivateKey, bytes uint64) *types.Transaction {
data := make([]byte, bytes) data := make([]byte, bytes)
rand.Read(data) crand.Read(data)
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key) tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(0), gaslimit, gasprice, data), types.HomesteadSigner{}, key)
return tx return tx

View file

@ -31,11 +31,6 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
var (
EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
EmptyUncleHash = rlpHash([]*Header(nil))
)
// A BlockNonce is a 64-bit hash which proves (combined with the // A BlockNonce is a 64-bit hash which proves (combined with the
// mix-hash) that a sufficient amount of computation has been carried // mix-hash) that a sufficient amount of computation has been carried
// out on a block. // out on a block.
@ -155,14 +150,14 @@ func (h *Header) SanityCheck() error {
// that is: no transactions, no uncles and no withdrawals. // that is: no transactions, no uncles and no withdrawals.
func (h *Header) EmptyBody() bool { func (h *Header) EmptyBody() bool {
if h.WithdrawalsHash == nil { if h.WithdrawalsHash == nil {
return h.TxHash == EmptyRootHash && h.UncleHash == EmptyUncleHash return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash
} }
return h.TxHash == EmptyRootHash && h.UncleHash == EmptyUncleHash && *h.WithdrawalsHash == EmptyRootHash return h.TxHash == EmptyTxsHash && h.UncleHash == EmptyUncleHash && *h.WithdrawalsHash == EmptyWithdrawalsHash
} }
// EmptyReceipts returns true if there are no receipts for this header/block. // EmptyReceipts returns true if there are no receipts for this header/block.
func (h *Header) EmptyReceipts() bool { func (h *Header) EmptyReceipts() bool {
return h.ReceiptHash == EmptyRootHash return h.ReceiptHash == EmptyReceiptsHash
} }
// Body is a simple (mutable, non-safe) data container for storing and moving // Body is a simple (mutable, non-safe) data container for storing and moving
@ -210,7 +205,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
// TODO: panic if len(txs) != len(receipts) // TODO: panic if len(txs) != len(receipts)
if len(txs) == 0 { if len(txs) == 0 {
b.header.TxHash = EmptyRootHash b.header.TxHash = EmptyTxsHash
} else { } else {
b.header.TxHash = DeriveSha(Transactions(txs), hasher) b.header.TxHash = DeriveSha(Transactions(txs), hasher)
b.transactions = make(Transactions, len(txs)) b.transactions = make(Transactions, len(txs))
@ -218,7 +213,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
} }
if len(receipts) == 0 { if len(receipts) == 0 {
b.header.ReceiptHash = EmptyRootHash b.header.ReceiptHash = EmptyReceiptsHash
} else { } else {
b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher) b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
b.header.Bloom = CreateBloom(receipts) b.header.Bloom = CreateBloom(receipts)
@ -250,7 +245,7 @@ func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Heade
if withdrawals == nil { if withdrawals == nil {
b.header.WithdrawalsHash = nil b.header.WithdrawalsHash = nil
} else if len(withdrawals) == 0 { } else if len(withdrawals) == 0 {
b.header.WithdrawalsHash = &EmptyRootHash b.header.WithdrawalsHash = &EmptyWithdrawalsHash
} else { } else {
h := DeriveSha(Withdrawals(withdrawals), hasher) h := DeriveSha(Withdrawals(withdrawals), hasher)
b.header.WithdrawalsHash = &h b.header.WithdrawalsHash = &h

42
core/types/hashes.go Normal file
View file

@ -0,0 +1,42 @@
// Copyright 2023 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 types
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
var (
// EmptyRootHash is the known root hash of an empty trie.
EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// EmptyUncleHash is the known hash of the empty uncle set.
EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347
// EmptyCodeHash is the known hash of the empty EVM bytecode.
EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
// EmptyTxsHash is the known hash of the empty transaction set.
EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// EmptyReceiptsHash is the known hash of the empty receipt set.
EmptyReceiptsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// EmptyWithdrawalsHash is the known hash of the empty withdrawal set.
EmptyWithdrawalsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
)

View file

@ -20,10 +20,9 @@
package signify package signify
import ( import (
"math/rand" "crypto/rand"
"os" "os"
"testing" "testing"
"time"
"github.com/jedisct1/go-minisign" "github.com/jedisct1/go-minisign"
) )
@ -41,8 +40,6 @@ func TestSignify(t *testing.T) {
defer os.Remove(tmpFile.Name()) defer os.Remove(tmpFile.Name())
defer tmpFile.Close() defer tmpFile.Close()
rand.Seed(time.Now().UnixNano())
data := make([]byte, 1024) data := make([]byte, 1024)
rand.Read(data) rand.Read(data)
tmpFile.Write(data) tmpFile.Write(data)
@ -85,8 +82,6 @@ func TestSignifyTrustedCommentTooManyLines(t *testing.T) {
defer os.Remove(tmpFile.Name()) defer os.Remove(tmpFile.Name())
defer tmpFile.Close() defer tmpFile.Close()
rand.Seed(time.Now().UnixNano())
data := make([]byte, 1024) data := make([]byte, 1024)
rand.Read(data) rand.Read(data)
tmpFile.Write(data) tmpFile.Write(data)
@ -110,8 +105,6 @@ func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) {
defer os.Remove(tmpFile.Name()) defer os.Remove(tmpFile.Name())
defer tmpFile.Close() defer tmpFile.Close()
rand.Seed(time.Now().UnixNano())
data := make([]byte, 1024) data := make([]byte, 1024)
rand.Read(data) rand.Read(data)
tmpFile.Write(data) tmpFile.Write(data)
@ -135,8 +128,6 @@ func TestSignifyTrustedCommentEmpty(t *testing.T) {
defer os.Remove(tmpFile.Name()) defer os.Remove(tmpFile.Name())
defer tmpFile.Close() defer tmpFile.Close()
rand.Seed(time.Now().UnixNano())
data := make([]byte, 1024) data := make([]byte, 1024)
rand.Read(data) rand.Read(data)
tmpFile.Write(data) tmpFile.Write(data)

View file

@ -134,7 +134,7 @@ func (api *PreExecAPI) GetLogs(ctx context.Context, origin *PreExecTx) (*types.R
gas := d.tx.Gas() gas := d.tx.Gas()
gp := new(core.GasPool).AddGas(gas) gp := new(core.GasPool).AddGas(gas)
d.stateDb.SetTxHashAndIndex(d.tx.Hash(), 0) d.stateDb.SetTxContext(d.tx.Hash(), 0)
receipt, err := core.ApplyTransactionForPreExec( receipt, err := core.ApplyTransactionForPreExec(
bc.Config(), bc, nil, gp, d.stateDb, d.header, d.tx, d.msg, &gas, *bc.GetVMConfig()) bc.Config(), bc, nil, gp, d.stateDb, d.header, d.tx, d.msg, &gas, *bc.GetVMConfig())
if err != nil { if err != nil {
@ -165,7 +165,7 @@ func (api *PreExecAPI) TraceTransaction(ctx context.Context, origin *PreExecTx)
vmenv.Context.Time += uint64(rand.Int63n(60) + 30) vmenv.Context.Time += uint64(rand.Int63n(60) + 30)
// Call Prepare to clear out the statedb access list // Call Prepare to clear out the statedb access list
d.stateDb.SetTxHashAndIndex(d.tx.Hash(), 0) d.stateDb.SetTxContext(d.tx.Hash(), 0)
tracer.SetMessage(d.block.Number(), d.block.Hash(), d.tx.Hash(), uint(txIndex), d.msg.From(), d.msg.To(), *d.msg.Value()) tracer.SetMessage(d.block.Number(), d.block.Hash(), d.tx.Hash(), uint(txIndex), d.msg.From(), d.msg.To(), *d.msg.Value())
@ -308,7 +308,7 @@ func (api *PreExecAPI) TraceMany(ctx context.Context, origins []PreArgs) ([]PreR
} }
// Execute the message. // Execute the message.
gp := new(core.GasPool).AddGas(math.MaxUint64) gp := new(core.GasPool).AddGas(math.MaxUint64)
state.SetTxHashAndIndex(txHash, i) state.SetTxContext(txHash, i)
result, err := core.ApplyMessage(evm, msg, gp) result, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil { if err := vmError(); err != nil {
preRes := PreResult{ preRes := PreResult{

View file

@ -448,7 +448,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
block, err := engine.ExecutableDataToBlock(params) block, err := engine.ExecutableDataToBlock(params)
if err != nil { if err != nil {
log.Debug("Invalid NewPayload params", "params", params, "error", err) log.Debug("Invalid NewPayload params", "params", params, "error", err)
return engine.PayloadStatusV1{Status: engine.INVALIDBLOCKHASH}, nil return engine.PayloadStatusV1{Status: engine.INVALID}, nil
} }
// Stash away the last update to warn the user if the beacon client goes offline // Stash away the last update to warn the user if the beacon client goes offline
api.lastNewPayloadLock.Lock() api.lastNewPayloadLock.Lock()
@ -785,9 +785,12 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range // GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
// of block bodies by the engine api. // of block bodies by the engine api.
func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV1, error) { func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV1, error) {
if start == 0 || count == 0 || count > 1024 { if start == 0 || count == 0 {
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count)) return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
} }
if count > 1024 {
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count))
}
// limit count up until current // limit count up until current
current := api.eth.BlockChain().CurrentBlock().NumberU64() current := api.eth.BlockChain().CurrentBlock().NumberU64()
last := uint64(start) + uint64(count) - 1 last := uint64(start) + uint64(count) - 1

View file

@ -864,8 +864,8 @@ func TestInvalidBloom(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if status.Status != engine.INVALIDBLOCKHASH { if status.Status != engine.INVALID {
t.Errorf("invalid status: expected VALID got: %v", status.Status) t.Errorf("invalid status: expected INVALID got: %v", status.Status)
} }
} }
@ -1383,37 +1383,43 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
node, eth, _ := setupBodies(t) node, eth, _ := setupBodies(t)
api := NewConsensusAPI(eth) api := NewConsensusAPI(eth)
defer node.Close() defer node.Close()
tests := []struct { tests := []struct {
start hexutil.Uint64 start hexutil.Uint64
count hexutil.Uint64 count hexutil.Uint64
want *engine.EngineAPIError
}{ }{
// Genesis // Genesis
{ {
start: 0, start: 0,
count: 1, count: 1,
want: engine.InvalidParams,
}, },
// No block requested // No block requested
{ {
start: 1, start: 1,
count: 0, count: 0,
want: engine.InvalidParams,
}, },
// Genesis & no block // Genesis & no block
{ {
start: 0, start: 0,
count: 0, count: 0,
want: engine.InvalidParams,
}, },
// More than 1024 blocks // More than 1024 blocks
{ {
start: 1, start: 1,
count: 1025, count: 1025,
want: engine.TooLargeRequest,
}, },
} }
for i, tc := range tests {
for _, test := range tests { result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count)
result, err := api.GetPayloadBodiesByRangeV1(test.start, test.count)
if err == nil { if err == nil {
t.Fatalf("expected error, got %v", result) t.Fatalf("test %d: expected error, got %v", i, result)
}
if have, want := err.Error(), tc.want.Error(); have != want {
t.Fatalf("test %d: have %s, want %s", i, have, want)
} }
} }
} }

View file

@ -154,6 +154,11 @@ type Downloader struct {
bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch bodyFetchHook func([]*types.Header) // Method to call upon starting a block body fetch
receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch receiptFetchHook func([]*types.Header) // Method to call upon starting a receipt fetch
chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations) chainInsertHook func([]*fetchResult) // Method to call upon inserting a chain of blocks (possibly in multiple invocations)
// Progress reporting metrics
syncStartBlock uint64 // Head snap block when Geth was started
syncStartTime time.Time // Time instance when chain sync started
syncLogTime time.Time // Time instance when status was last reported
} }
// LightChain encapsulates functions required to synchronise a light chain. // LightChain encapsulates functions required to synchronise a light chain.
@ -231,7 +236,9 @@ func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain Bl
quitCh: make(chan struct{}), quitCh: make(chan struct{}),
SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()), SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()),
stateSyncStart: make(chan *stateSync), stateSyncStart: make(chan *stateSync),
syncStartBlock: chain.CurrentFastBlock().NumberU64(),
} }
// Create the post-merge skeleton syncer and start the process
dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success)) dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success))
go dl.stateFetcher() go dl.stateFetcher()
@ -1614,6 +1621,7 @@ func (d *Downloader) processSnapSyncContent() error {
if len(results) == 0 { if len(results) == 0 {
// If pivot sync is done, stop // If pivot sync is done, stop
if oldPivot == nil { if oldPivot == nil {
d.reportSnapSyncProgress(true)
return sync.Cancel() return sync.Cancel()
} }
// If sync failed, stop // If sync failed, stop
@ -1627,6 +1635,8 @@ func (d *Downloader) processSnapSyncContent() error {
if d.chainInsertHook != nil { if d.chainInsertHook != nil {
d.chainInsertHook(results) d.chainInsertHook(results)
} }
d.reportSnapSyncProgress(false)
// If we haven't downloaded the pivot block yet, check pivot staleness // If we haven't downloaded the pivot block yet, check pivot staleness
// notifications from the header downloader // notifications from the header downloader
d.pivotLock.RLock() d.pivotLock.RLock()
@ -1739,7 +1749,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
} }
default: default:
} }
// Retrieve the a batch of results to import // Retrieve the batch of results to import
first, last := results[0].Header, results[len(results)-1].Header first, last := results[0].Header, results[len(results)-1].Header
log.Debug("Inserting snap-sync blocks", "items", len(results), log.Debug("Inserting snap-sync blocks", "items", len(results),
"firstnum", first.Number, "firsthash", first.Hash(), "firstnum", first.Number, "firsthash", first.Hash(),
@ -1820,3 +1830,56 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea
} }
return headers return headers
} }
// reportSnapSyncProgress calculates various status reports and provides it to the user.
func (d *Downloader) reportSnapSyncProgress(force bool) {
// Initialize the sync start time if it's the first time we're reporting
if d.syncStartTime.IsZero() {
d.syncStartTime = time.Now().Add(-time.Millisecond) // -1ms offset to avoid division by zero
}
// Don't report all the events, just occasionally
if !force && time.Since(d.syncLogTime) < 8*time.Second {
return
}
// Don't report anything until we have a meaningful progress
var (
headerBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerHeaderTable)
bodyBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerBodiesTable)
receiptBytes, _ = d.stateDB.AncientSize(rawdb.ChainFreezerReceiptTable)
)
syncedBytes := common.StorageSize(headerBytes + bodyBytes + receiptBytes)
if syncedBytes == 0 {
return
}
var (
header = d.blockchain.CurrentHeader()
block = d.blockchain.CurrentFastBlock()
)
syncedBlocks := block.NumberU64() - d.syncStartBlock
if syncedBlocks == 0 {
return
}
// Retrieve the current chain head and calculate the ETA
latest, _, err := d.skeleton.Bounds()
if err != nil {
// We're going to cheat for non-merged networks, but that's fine
latest = d.pivotHeader
}
if latest == nil {
// This should really never happen, but add some defensive code for now.
// TODO(karalabe): Remove it eventually if we don't see it blow.
log.Error("Nil latest block in sync progress report")
return
}
var (
left = latest.Number.Uint64() - block.NumberU64()
eta = time.Since(d.syncStartTime) / time.Duration(syncedBlocks) * time.Duration(left)
progress = fmt.Sprintf("%.2f%%", float64(block.NumberU64())*100/float64(latest.Number.Uint64()))
headers = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(header.Number.Uint64()), common.StorageSize(headerBytes).TerminalString())
bodies = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.NumberU64()), common.StorageSize(bodyBytes).TerminalString())
receipts = fmt.Sprintf("%v@%v", log.FormatLogfmtUint64(block.NumberU64()), common.StorageSize(receiptBytes).TerminalString())
)
log.Info("Syncing: chain download in progress", "synced", progress, "chain", syncedBytes, "headers", headers, "bodies", bodies, "receipts", receipts, "eta", common.PrettyDuration(eta))
d.syncLogTime = time.Now()
}

View file

@ -76,6 +76,8 @@ func newFetchResult(header *types.Header, fastSync bool) *fetchResult {
} }
if !header.EmptyBody() { if !header.EmptyBody() {
item.pending |= (1 << bodyType) item.pending |= (1 << bodyType)
} else if header.WithdrawalsHash != nil {
item.Withdrawals = make(types.Withdrawals, 0)
} }
if fastSync && !header.EmptyReceipts() { if fastSync && !header.EmptyReceipts() {
item.pending |= (1 << receiptType) item.pending |= (1 << receiptType)
@ -142,7 +144,7 @@ type queue struct {
active *sync.Cond active *sync.Cond
closed bool closed bool
lastStatLog time.Time logTime time.Time // Time instance when status was last reported
} }
// newQueue creates a new download queue for scheduling block retrieval. // newQueue creates a new download queue for scheduling block retrieval.
@ -388,11 +390,12 @@ func (q *queue) Results(block bool) []*fetchResult {
} }
} }
// Log some info at certain times // Log some info at certain times
if time.Since(q.lastStatLog) > 60*time.Second { if time.Since(q.logTime) >= 60*time.Second {
q.lastStatLog = time.Now() q.logTime = time.Now()
info := q.Stats() info := q.Stats()
info = append(info, "throttle", throttleThreshold) info = append(info, "throttle", throttleThreshold)
log.Info("Downloader queue stats", info...) log.Debug("Downloader queue stats", info...)
} }
return results return results
} }
@ -781,15 +784,18 @@ func (q *queue) DeliverBodies(id string, txLists [][]*types.Transaction, txListH
return errInvalidBody return errInvalidBody
} }
if header.WithdrawalsHash == nil { if header.WithdrawalsHash == nil {
// discard any withdrawals if we don't have a withdrawal hash set // nil hash means that withdrawals should not be present in body
withdrawalLists[index] = nil if withdrawalLists[index] != nil {
} else if *header.WithdrawalsHash == types.EmptyRootHash && withdrawalLists[index] == nil {
// if the withdrawal hash is the emptyRootHash,
// we expect withdrawals to be [] instead of nil
withdrawalLists[index] = make([]*types.Withdrawal, 0)
} else if withdrawalListHashes[index] != *header.WithdrawalsHash {
return errInvalidBody return errInvalidBody
} }
} else { // non-nil hash: body must have withdrawals
if withdrawalLists[index] == nil {
return errInvalidBody
}
if withdrawalListHashes[index] != *header.WithdrawalsHash {
return errInvalidBody
}
}
return nil return nil
} }

View file

@ -599,7 +599,7 @@ func (f *BlockFetcher) loop() {
announce.time = task.time announce.time = task.time
// If the block is empty (header only), short circuit into the final import queue // If the block is empty (header only), short circuit into the final import queue
if header.TxHash == types.EmptyRootHash && header.UncleHash == types.EmptyUncleHash { if header.TxHash == types.EmptyTxsHash && header.UncleHash == types.EmptyUncleHash {
log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash()) log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash())
block := types.NewBlockWithHeader(header) block := types.NewBlockWithHeader(header)

View file

@ -39,6 +39,7 @@ type filter struct {
typ Type typ Type
deadline *time.Timer // filter is inactive when deadline triggers deadline *time.Timer // filter is inactive when deadline triggers
hashes []common.Hash hashes []common.Hash
fullTx bool
txs []*types.Transaction txs []*types.Transaction
crit FilterCriteria crit FilterCriteria
logs []*types.Log logs []*types.Log
@ -103,14 +104,14 @@ func (api *FilterAPI) timeoutLoop(timeout time.Duration) {
// //
// It is part of the filter package because this filter can be used through the // It is part of the filter package because this filter can be used through the
// `eth_getFilterChanges` polling method that is also used for log filters. // `eth_getFilterChanges` polling method that is also used for log filters.
func (api *FilterAPI) NewPendingTransactionFilter() rpc.ID { func (api *FilterAPI) NewPendingTransactionFilter(fullTx *bool) rpc.ID {
var ( var (
pendingTxs = make(chan []*types.Transaction) pendingTxs = make(chan []*types.Transaction)
pendingTxSub = api.events.SubscribePendingTxs(pendingTxs) pendingTxSub = api.events.SubscribePendingTxs(pendingTxs)
) )
api.filtersMu.Lock() api.filtersMu.Lock()
api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub} api.filters[pendingTxSub.ID] = &filter{typ: PendingTransactionsSubscription, fullTx: fullTx != nil && *fullTx, deadline: time.NewTimer(api.timeout), txs: make([]*types.Transaction, 0), s: pendingTxSub}
api.filtersMu.Unlock() api.filtersMu.Unlock()
go func() { go func() {
@ -412,6 +413,9 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) {
api.filtersMu.Lock() api.filtersMu.Lock()
defer api.filtersMu.Unlock() defer api.filtersMu.Unlock()
chainConfig := api.sys.backend.ChainConfig()
latest := api.sys.backend.CurrentHeader()
if f, found := api.filters[id]; found { if f, found := api.filters[id]; found {
if !f.deadline.Stop() { if !f.deadline.Stop() {
// timer expired but filter is not yet removed in timeout loop // timer expired but filter is not yet removed in timeout loop
@ -426,9 +430,21 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) {
f.hashes = nil f.hashes = nil
return returnHashes(hashes), nil return returnHashes(hashes), nil
case PendingTransactionsSubscription: case PendingTransactionsSubscription:
txs := f.txs if f.fullTx {
txs := make([]*ethapi.RPCTransaction, 0, len(f.txs))
for _, tx := range f.txs {
txs = append(txs, ethapi.NewRPCPendingTransaction(tx, latest, chainConfig))
}
f.txs = nil f.txs = nil
return txs, nil return txs, nil
} else {
hashes := make([]common.Hash, 0, len(f.txs))
for _, tx := range f.txs {
hashes = append(hashes, tx.Hash())
}
f.txs = nil
return hashes, nil
}
case LogsSubscription, MinedAndPendingLogsSubscription: case LogsSubscription, MinedAndPendingLogsSubscription:
logs := f.logs logs := f.logs
f.logs = nil f.logs = nil

View file

@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -52,11 +53,12 @@ type testBackend struct {
} }
func (b *testBackend) ChainConfig() *params.ChainConfig { func (b *testBackend) ChainConfig() *params.ChainConfig {
panic("implement me") return params.TestChainConfig
} }
func (b *testBackend) CurrentHeader() *types.Header { func (b *testBackend) CurrentHeader() *types.Header {
panic("implement me") hdr, _ := b.HeaderByNumber(context.TODO(), rpc.LatestBlockNumber)
return hdr
} }
func (b *testBackend) ChainDb() ethdb.Database { func (b *testBackend) ChainDb() ethdb.Database {
@ -256,10 +258,10 @@ func TestPendingTxFilter(t *testing.T) {
types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil), types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
} }
txs []*types.Transaction hashes []common.Hash
) )
fid0 := api.NewPendingTransactionFilter() fid0 := api.NewPendingTransactionFilter(nil)
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
backend.txFeed.Send(core.NewTxsEvent{Txs: transactions}) backend.txFeed.Send(core.NewTxsEvent{Txs: transactions})
@ -271,7 +273,64 @@ func TestPendingTxFilter(t *testing.T) {
t.Fatalf("Unable to retrieve logs: %v", err) t.Fatalf("Unable to retrieve logs: %v", err)
} }
tx := results.([]*types.Transaction) h := results.([]common.Hash)
hashes = append(hashes, h...)
if len(hashes) >= len(transactions) {
break
}
// check timeout
if time.Now().After(timeout) {
break
}
time.Sleep(100 * time.Millisecond)
}
if len(hashes) != len(transactions) {
t.Errorf("invalid number of transactions, want %d transactions(s), got %d", len(transactions), len(hashes))
return
}
for i := range hashes {
if hashes[i] != transactions[i].Hash() {
t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), hashes[i])
}
}
}
// TestPendingTxFilterFullTx tests whether pending tx filters retrieve all pending transactions that are posted to the event mux.
func TestPendingTxFilterFullTx(t *testing.T) {
t.Parallel()
var (
db = rawdb.NewMemoryDatabase()
backend, sys = newTestFilterSystem(t, db, Config{})
api = NewFilterAPI(sys, false)
transactions = []*types.Transaction{
types.NewTransaction(0, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(1, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(2, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(3, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
types.NewTransaction(4, common.HexToAddress("0xb794f5ea0ba39494ce83a213fffba74279579268"), new(big.Int), 0, new(big.Int), nil),
}
txs []*ethapi.RPCTransaction
)
fullTx := true
fid0 := api.NewPendingTransactionFilter(&fullTx)
time.Sleep(1 * time.Second)
backend.txFeed.Send(core.NewTxsEvent{Txs: transactions})
timeout := time.Now().Add(1 * time.Second)
for {
results, err := api.GetFilterChanges(fid0)
if err != nil {
t.Fatalf("Unable to retrieve logs: %v", err)
}
tx := results.([]*ethapi.RPCTransaction)
txs = append(txs, tx...) txs = append(txs, tx...)
if len(txs) >= len(transactions) { if len(txs) >= len(transactions) {
break break
@ -289,8 +348,8 @@ func TestPendingTxFilter(t *testing.T) {
return return
} }
for i := range txs { for i := range txs {
if txs[i].Hash() != transactions[i].Hash() { if txs[i].Hash != transactions[i].Hash() {
t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash()) t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[i].Hash)
} }
} }
} }
@ -854,15 +913,15 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
// timeout either in 100ms or 200ms // timeout either in 100ms or 200ms
fids := make([]rpc.ID, 20) fids := make([]rpc.ID, 20)
for i := 0; i < len(fids); i++ { for i := 0; i < len(fids); i++ {
fid := api.NewPendingTransactionFilter() fid := api.NewPendingTransactionFilter(nil)
fids[i] = fid fids[i] = fid
// Wait for at least one tx to arrive in filter // Wait for at least one tx to arrive in filter
for { for {
txs, err := api.GetFilterChanges(fid) hashes, err := api.GetFilterChanges(fid)
if err != nil { if err != nil {
t.Fatalf("Filter should exist: %v\n", err) t.Fatalf("Filter should exist: %v\n", err)
} }
if len(txs.([]*types.Transaction)) > 0 { if len(hashes.([]common.Hash)) > 0 {
break break
} }
runtime.Gosched() runtime.Gosched()

View file

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
@ -464,7 +465,7 @@ func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [
bytes uint64 bytes uint64
) )
for _, hash := range req.Hashes { for _, hash := range req.Hashes {
if hash == emptyCode { if hash == types.EmptyCodeHash {
// Peers should not request the empty code, but if they do, at // Peers should not request the empty code, but if they do, at
// least sent them back a correct response without db lookups // least sent them back a correct response without db lookups
codes = append(codes, []byte{}) codes = append(codes, []byte{})

View file

@ -46,14 +46,6 @@ import (
"golang.org/x/crypto/sha3" "golang.org/x/crypto/sha3"
) )
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyCode is the known hash of the empty EVM bytecode.
emptyCode = crypto.Keccak256Hash(nil)
)
const ( const (
// minRequestSize is the minimum number of bytes to request from a remote peer. // minRequestSize is the minimum number of bytes to request from a remote peer.
// This number is used as the low cap for account and storage range requests. // This number is used as the low cap for account and storage range requests.
@ -1833,7 +1825,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
res.task.pend = 0 res.task.pend = 0
for i, account := range res.accounts { for i, account := range res.accounts {
// Check if the account is a contract with an unknown code // Check if the account is a contract with an unknown code
if !bytes.Equal(account.CodeHash, emptyCode[:]) { if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) { if !rawdb.HasCodeWithPrefix(s.db, common.BytesToHash(account.CodeHash)) {
res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{} res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{}
res.task.needCode[i] = true res.task.needCode[i] = true
@ -1841,7 +1833,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
} }
} }
// Check if the account is a contract with an unknown storage trie // Check if the account is a contract with an unknown storage trie
if account.Root != emptyRoot { if account.Root != types.EmptyRootHash {
if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) { if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) {
// If there was a previous large state retrieval in progress, // If there was a previous large state retrieval in progress,
// don't restart it from scratch. This happens if a sync cycle // don't restart it from scratch. This happens if a sync cycle

View file

@ -1354,7 +1354,7 @@ func getCodeHash(i uint64) []byte {
// getCodeByHash convenience function to lookup the code from the code hash // getCodeByHash convenience function to lookup the code from the code hash
func getCodeByHash(hash common.Hash) []byte { func getCodeByHash(hash common.Hash) []byte {
if hash == emptyCode { if hash == types.EmptyCodeHash {
return nil return nil
} }
for i, h := range codehashes { for i, h := range codehashes {
@ -1376,7 +1376,7 @@ func makeAccountTrieNoStorage(n int) (string, *trie.Trie, entrySlice) {
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i, Nonce: i,
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: emptyRoot, Root: types.EmptyRootHash,
CodeHash: getCodeHash(i), CodeHash: getCodeHash(i),
}) })
key := key32(i) key := key32(i)
@ -1427,7 +1427,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: uint64(0), Nonce: uint64(0),
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: emptyRoot, Root: types.EmptyRootHash,
CodeHash: getCodeHash(uint64(i)), CodeHash: getCodeHash(uint64(i)),
}) })
elem := &kv{boundaries[i].Bytes(), value} elem := &kv{boundaries[i].Bytes(), value}
@ -1439,7 +1439,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
value, _ := rlp.EncodeToBytes(&types.StateAccount{ value, _ := rlp.EncodeToBytes(&types.StateAccount{
Nonce: i, Nonce: i,
Balance: big.NewInt(int64(i)), Balance: big.NewInt(int64(i)),
Root: emptyRoot, Root: types.EmptyRootHash,
CodeHash: getCodeHash(i), CodeHash: getCodeHash(i),
}) })
elem := &kv{key32(i), value} elem := &kv{key32(i), value}
@ -1472,7 +1472,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
// Create n accounts in the trie // Create n accounts in the trie
for i := uint64(1); i <= uint64(accounts); i++ { for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i) key := key32(i)
codehash := emptyCode[:] codehash := types.EmptyCodeHash.Bytes()
if code { if code {
codehash = getCodeHash(i) codehash = getCodeHash(i)
} }
@ -1527,7 +1527,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
// Create n accounts in the trie // Create n accounts in the trie
for i := uint64(1); i <= uint64(accounts); i++ { for i := uint64(1); i <= uint64(accounts); i++ {
key := key32(i) key := key32(i)
codehash := emptyCode[:] codehash := types.EmptyCodeHash.Bytes()
if code { if code {
codehash = getCodeHash(i) codehash = getCodeHash(i)
} }
@ -1678,7 +1678,7 @@ func verifyTrie(db ethdb.KeyValueStore, root common.Hash, t *testing.T) {
log.Crit("Invalid account encountered during snapshot creation", "err", err) log.Crit("Invalid account encountered during snapshot creation", "err", err)
} }
accounts++ accounts++
if acc.Root != emptyRoot { if acc.Root != types.EmptyRootHash {
id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root) id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root)
storeTrie, err := trie.NewStateTrie(id, triedb) storeTrie, err := trie.NewStateTrie(id, triedb)
if err != nil { if err != nil {

View file

@ -131,10 +131,10 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 { if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 {
return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles") return nil, fmt.Errorf("server returned empty uncle list but block header indicates uncles")
} }
if head.TxHash == types.EmptyRootHash && len(body.Transactions) > 0 { if head.TxHash == types.EmptyTxsHash && len(body.Transactions) > 0 {
return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions") return nil, fmt.Errorf("server returned non-empty transaction list but block header indicates no transactions")
} }
if head.TxHash != types.EmptyRootHash && len(body.Transactions) == 0 { if head.TxHash != types.EmptyTxsHash && len(body.Transactions) == 0 {
return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions") return nil, fmt.Errorf("server returned empty transaction list but block header indicates transactions")
} }
// Load uncles because they are not included in the block response. // Load uncles because they are not included in the block response.

View file

@ -18,7 +18,7 @@ package dbtest
import ( import (
"bytes" "bytes"
"math/rand" "crypto/rand"
"reflect" "reflect"
"sort" "sort"
"testing" "testing"

View file

@ -100,7 +100,6 @@ func TestSubscribeDuplicateType(t *testing.T) {
} }
func TestMuxConcurrent(t *testing.T) { func TestMuxConcurrent(t *testing.T) {
rand.Seed(time.Now().Unix())
mux := new(TypeMux) mux := new(TypeMux)
defer mux.Stop() defer mux.Stop()

View file

@ -18,6 +18,7 @@ package les
import ( import (
"context" "context"
crand "crypto/rand"
"errors" "errors"
"flag" "flag"
"math/rand" "math/rand"
@ -326,7 +327,7 @@ func getHead(ctx context.Context, t *testing.T, client *rpc.Client) (uint64, com
func testRequest(ctx context.Context, t *testing.T, client *rpc.Client) bool { func testRequest(ctx context.Context, t *testing.T, client *rpc.Client) bool {
var res string var res string
var addr common.Address var addr common.Address
rand.Read(addr[:]) crand.Read(addr[:])
c, cancel := context.WithTimeout(ctx, time.Second*12) c, cancel := context.WithTimeout(ctx, time.Second*12)
defer cancel() defer cancel()
err := client.CallContext(c, &res, "eth_getBalance", addr, "latest") err := client.CallContext(c, &res, "eth_getBalance", addr, "latest")

View file

@ -17,6 +17,7 @@
package les package les
import ( import (
crand "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/big" "math/big"
@ -114,7 +115,7 @@ func (b *benchmarkProofsOrCode) init(h *serverHandler, count int) error {
func (b *benchmarkProofsOrCode) request(peer *serverPeer, index int) error { func (b *benchmarkProofsOrCode) request(peer *serverPeer, index int) error {
key := make([]byte, 32) key := make([]byte, 32)
rand.Read(key) crand.Read(key)
if b.code { if b.code {
return peer.requestCode(0, []CodeReq{{BHash: b.headHash, AccKey: key}}) return peer.requestCode(0, []CodeReq{{BHash: b.headHash, AccKey: key}})
} }
@ -176,7 +177,7 @@ func (b *benchmarkTxSend) init(h *serverHandler, count int) error {
for i := range b.txs { for i := range b.txs {
data := make([]byte, txSizeCostLimit) data := make([]byte, txSizeCostLimit)
rand.Read(data) crand.Read(data)
tx, err := types.SignTx(types.NewTransaction(0, addr, new(big.Int), 0, new(big.Int), data), signer, key) tx, err := types.SignTx(types.NewTransaction(0, addr, new(big.Int), 0, new(big.Int), data), signer, key)
if err != nil { if err != nil {
panic(err) panic(err)
@ -200,7 +201,7 @@ func (b *benchmarkTxStatus) init(h *serverHandler, count int) error {
func (b *benchmarkTxStatus) request(peer *serverPeer, index int) error { func (b *benchmarkTxStatus) request(peer *serverPeer, index int) error {
var hash common.Hash var hash common.Hash
rand.Read(hash[:]) crand.Read(hash[:])
return peer.requestTxStatus(0, []common.Hash{hash}) return peer.requestTxStatus(0, []common.Hash{hash})
} }
@ -278,7 +279,7 @@ func (h *serverHandler) measure(setup *benchmarkSetup, count int) error {
clientMeteredPipe := &meteredPipe{rw: clientPipe} clientMeteredPipe := &meteredPipe{rw: clientPipe}
serverMeteredPipe := &meteredPipe{rw: serverPipe} serverMeteredPipe := &meteredPipe{rw: serverPipe}
var id enode.ID var id enode.ID
rand.Read(id[:]) crand.Read(id[:])
peer1 := newServerPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe) peer1 := newServerPeer(lpv2, NetworkId, false, p2p.NewPeer(id, "client", nil), clientMeteredPipe)
peer2 := newClientPeer(lpv2, NetworkId, p2p.NewPeer(id, "server", nil), serverMeteredPipe) peer2 := newClientPeer(lpv2, NetworkId, p2p.NewPeer(id, "server", nil), serverMeteredPipe)

View file

@ -548,7 +548,7 @@ func (f *BlockFetcher) loop() {
announce.time = task.time announce.time = task.time
// If the block is empty (header only), short circuit into the final import queue // If the block is empty (header only), short circuit into the final import queue
if header.TxHash == types.EmptyRootHash && header.UncleHash == types.EmptyUncleHash { if header.TxHash == types.EmptyTxsHash && header.UncleHash == types.EmptyUncleHash {
log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash()) log.Trace("Block empty, skipping body retrieval", "peer", announce.origin, "number", header.Number, "hash", header.Hash())
block := types.NewBlockWithHeader(header) block := types.NewBlockWithHeader(header)

View file

@ -348,7 +348,7 @@ func handleGetReceipts(msg Decoder) (serveRequestFn, uint64, uint64, error) {
// Retrieve the requested block's receipts, skipping if unknown to us // Retrieve the requested block's receipts, skipping if unknown to us
results := bc.GetReceiptsByHash(hash) results := bc.GetReceiptsByHash(hash)
if results == nil { if results == nil {
if header := bc.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { if header := bc.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyReceiptsHash {
p.bumpInvalid() p.bumpInvalid()
continue continue
} }

View file

@ -17,7 +17,7 @@
package utils package utils
import ( import (
"math/rand" "crypto/rand"
"testing" "testing"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"

View file

@ -17,7 +17,7 @@
package client package client
import ( import (
"math/rand" "crypto/rand"
"testing" "testing"
"time" "time"

View file

@ -135,7 +135,6 @@ func alwaysTrueFn() bool {
} }
func testClientPool(t *testing.T, activeLimit, clientCount, paidCount int, randomDisconnect bool) { func testClientPool(t *testing.T, activeLimit, clientCount, paidCount int, randomDisconnect bool) {
rand.Seed(time.Now().UnixNano())
var ( var (
clock mclock.Simulated clock mclock.Simulated
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()

View file

@ -253,8 +253,8 @@ func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.
Number: big.NewInt(int64(i + 1)), Number: big.NewInt(int64(i + 1)),
Difficulty: big.NewInt(int64(difficulty)), Difficulty: big.NewInt(int64(difficulty)),
UncleHash: types.EmptyUncleHash, UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash, TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyRootHash, ReceiptHash: types.EmptyReceiptsHash,
} }
if i == 0 { if i == 0 {
header.ParentHash = genesis.Hash() header.ParentHash = genesis.Hash()

View file

@ -41,6 +41,7 @@ type ExpDecaySample struct {
reservoirSize int reservoirSize int
t0, t1 time.Time t0, t1 time.Time
values *expDecaySampleHeap values *expDecaySampleHeap
rand *rand.Rand
} }
// NewExpDecaySample constructs a new exponentially-decaying sample with the // NewExpDecaySample constructs a new exponentially-decaying sample with the
@ -59,6 +60,12 @@ func NewExpDecaySample(reservoirSize int, alpha float64) Sample {
return s return s
} }
// SetRand sets the random source (useful in tests)
func (s *ExpDecaySample) SetRand(prng *rand.Rand) Sample {
s.rand = prng
return s
}
// Clear clears all samples. // Clear clears all samples.
func (s *ExpDecaySample) Clear() { func (s *ExpDecaySample) Clear() {
s.mutex.Lock() s.mutex.Lock()
@ -168,8 +175,14 @@ func (s *ExpDecaySample) update(t time.Time, v int64) {
if s.values.Size() == s.reservoirSize { if s.values.Size() == s.reservoirSize {
s.values.Pop() s.values.Pop()
} }
var f64 float64
if s.rand != nil {
f64 = s.rand.Float64()
} else {
f64 = rand.Float64()
}
s.values.Push(expDecaySample{ s.values.Push(expDecaySample{
k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / rand.Float64(), k: math.Exp(t.Sub(s.t0).Seconds()*s.alpha) / f64,
v: v, v: v,
}) })
if t.After(s.t1) { if t.After(s.t1) {
@ -402,6 +415,7 @@ type UniformSample struct {
mutex sync.Mutex mutex sync.Mutex
reservoirSize int reservoirSize int
values []int64 values []int64
rand *rand.Rand
} }
// NewUniformSample constructs a new uniform sample with the given reservoir // NewUniformSample constructs a new uniform sample with the given reservoir
@ -416,6 +430,12 @@ func NewUniformSample(reservoirSize int) Sample {
} }
} }
// SetRand sets the random source (useful in tests)
func (s *UniformSample) SetRand(prng *rand.Rand) Sample {
s.rand = prng
return s
}
// Clear clears all samples. // Clear clears all samples.
func (s *UniformSample) Clear() { func (s *UniformSample) Clear() {
s.mutex.Lock() s.mutex.Lock()
@ -511,7 +531,12 @@ func (s *UniformSample) Update(v int64) {
if len(s.values) < s.reservoirSize { if len(s.values) < s.reservoirSize {
s.values = append(s.values, v) s.values = append(s.values, v)
} else { } else {
r := rand.Int63n(s.count) var r int64
if s.rand != nil {
r = s.rand.Int63n(s.count)
} else {
r = rand.Int63n(s.count)
}
if r < int64(len(s.values)) { if r < int64(len(s.values)) {
s.values[int(r)] = v s.values[int(r)] = v
} }

View file

@ -80,7 +80,6 @@ func BenchmarkUniformSample1028(b *testing.B) {
} }
func TestExpDecaySample10(t *testing.T) { func TestExpDecaySample10(t *testing.T) {
rand.Seed(1)
s := NewExpDecaySample(100, 0.99) s := NewExpDecaySample(100, 0.99)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
s.Update(int64(i)) s.Update(int64(i))
@ -102,7 +101,6 @@ func TestExpDecaySample10(t *testing.T) {
} }
func TestExpDecaySample100(t *testing.T) { func TestExpDecaySample100(t *testing.T) {
rand.Seed(1)
s := NewExpDecaySample(1000, 0.01) s := NewExpDecaySample(1000, 0.01)
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
s.Update(int64(i)) s.Update(int64(i))
@ -124,7 +122,6 @@ func TestExpDecaySample100(t *testing.T) {
} }
func TestExpDecaySample1000(t *testing.T) { func TestExpDecaySample1000(t *testing.T) {
rand.Seed(1)
s := NewExpDecaySample(100, 0.99) s := NewExpDecaySample(100, 0.99)
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
s.Update(int64(i)) s.Update(int64(i))
@ -150,7 +147,6 @@ func TestExpDecaySample1000(t *testing.T) {
// The priority becomes +Inf quickly after starting if this is done, // The priority becomes +Inf quickly after starting if this is done,
// effectively freezing the set of samples until a rescale step happens. // effectively freezing the set of samples until a rescale step happens.
func TestExpDecaySampleNanosecondRegression(t *testing.T) { func TestExpDecaySampleNanosecondRegression(t *testing.T) {
rand.Seed(1)
s := NewExpDecaySample(100, 0.99) s := NewExpDecaySample(100, 0.99)
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
s.Update(10) s.Update(10)
@ -183,8 +179,7 @@ func TestExpDecaySampleRescale(t *testing.T) {
func TestExpDecaySampleSnapshot(t *testing.T) { func TestExpDecaySampleSnapshot(t *testing.T) {
now := time.Now() now := time.Now()
rand.Seed(1) s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1)))
s := NewExpDecaySample(100, 0.99)
for i := 1; i <= 10000; i++ { for i := 1; i <= 10000; i++ {
s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i))
} }
@ -195,8 +190,7 @@ func TestExpDecaySampleSnapshot(t *testing.T) {
func TestExpDecaySampleStatistics(t *testing.T) { func TestExpDecaySampleStatistics(t *testing.T) {
now := time.Now() now := time.Now()
rand.Seed(1) s := NewExpDecaySample(100, 0.99).(*ExpDecaySample).SetRand(rand.New(rand.NewSource(1)))
s := NewExpDecaySample(100, 0.99)
for i := 1; i <= 10000; i++ { for i := 1; i <= 10000; i++ {
s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i)) s.(*ExpDecaySample).update(now.Add(time.Duration(i)), int64(i))
} }
@ -204,7 +198,6 @@ func TestExpDecaySampleStatistics(t *testing.T) {
} }
func TestUniformSample(t *testing.T) { func TestUniformSample(t *testing.T) {
rand.Seed(1)
s := NewUniformSample(100) s := NewUniformSample(100)
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
s.Update(int64(i)) s.Update(int64(i))
@ -226,7 +219,6 @@ func TestUniformSample(t *testing.T) {
} }
func TestUniformSampleIncludesTail(t *testing.T) { func TestUniformSampleIncludesTail(t *testing.T) {
rand.Seed(1)
s := NewUniformSample(100) s := NewUniformSample(100)
max := 100 max := 100
for i := 0; i < max; i++ { for i := 0; i < max; i++ {
@ -244,7 +236,7 @@ func TestUniformSampleIncludesTail(t *testing.T) {
} }
func TestUniformSampleSnapshot(t *testing.T) { func TestUniformSampleSnapshot(t *testing.T) {
s := NewUniformSample(100) s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1)))
for i := 1; i <= 10000; i++ { for i := 1; i <= 10000; i++ {
s.Update(int64(i)) s.Update(int64(i))
} }
@ -254,8 +246,7 @@ func TestUniformSampleSnapshot(t *testing.T) {
} }
func TestUniformSampleStatistics(t *testing.T) { func TestUniformSampleStatistics(t *testing.T) {
rand.Seed(1) s := NewUniformSample(100).(*UniformSample).SetRand(rand.New(rand.NewSource(1)))
s := NewUniformSample(100)
for i := 1; i <= 10000; i++ { for i := 1; i <= 10000; i++ {
s.Update(int64(i)) s.Update(int64(i))
} }

View file

@ -19,6 +19,7 @@ package main
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
crand "crypto/rand"
"math/big" "math/big"
"math/rand" "math/rand"
"os" "os"
@ -162,7 +163,7 @@ func makeTransaction(nonce uint64, privKey *ecdsa.PrivateKey, signer types.Signe
// Feecap and feetip are limited to 32 bytes. Offer a sightly // Feecap and feetip are limited to 32 bytes. Offer a sightly
// larger buffer for creating both valid and invalid transactions. // larger buffer for creating both valid and invalid transactions.
var buf = make([]byte, 32+5) var buf = make([]byte, 32+5)
rand.Read(buf) crand.Read(buf)
gasTipCap := new(big.Int).SetBytes(buf) gasTipCap := new(big.Int).SetBytes(buf)
// If the given base fee is nil(the 1559 is still not available), // If the given base fee is nil(the 1559 is still not available),
@ -173,7 +174,7 @@ func makeTransaction(nonce uint64, privKey *ecdsa.PrivateKey, signer types.Signe
// Generate the feecap, 75% valid feecap and 25% unguaranteed. // Generate the feecap, 75% valid feecap and 25% unguaranteed.
var gasFeeCap *big.Int var gasFeeCap *big.Int
if rand.Intn(4) == 0 { if rand.Intn(4) == 0 {
rand.Read(buf) crand.Read(buf)
gasFeeCap = new(big.Int).SetBytes(buf) gasFeeCap = new(big.Int).SetBytes(buf)
} else { } else {
gasFeeCap = new(big.Int).Add(baseFee, gasTipCap) gasFeeCap = new(big.Int).Add(baseFee, gasTipCap)

View file

@ -17,9 +17,9 @@
package miner package miner
import ( import (
"crypto/rand"
"errors" "errors"
"math/big" "math/big"
"math/rand"
"sync/atomic" "sync/atomic"
"testing" "testing"
"time" "time"
@ -105,8 +105,6 @@ func init() {
GasPrice: big.NewInt(params.InitialBaseFee), GasPrice: big.NewInt(params.InitialBaseFee),
}) })
newTxs = append(newTxs, tx2) newTxs = append(newTxs, tx2)
rand.Seed(time.Now().UnixNano())
} }
// testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing. // testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing.

View file

@ -165,7 +165,6 @@ func TestUDPv4_responseTimeouts(t *testing.T) {
test := newUDPTest(t) test := newUDPTest(t)
defer test.close() defer test.close()
rand.Seed(time.Now().UnixNano())
randomDuration := func(max time.Duration) time.Duration { randomDuration := func(max time.Duration) time.Duration {
return time.Duration(rand.Int63n(int64(max))) return time.Duration(rand.Int63n(int64(max)))
} }

View file

@ -17,7 +17,7 @@
package enode package enode
import ( import (
"math/rand" "crypto/rand"
"net" "net"
"testing" "testing"

View file

@ -17,8 +17,8 @@
package netutil package netutil
import ( import (
crand "crypto/rand"
"fmt" "fmt"
mrand "math/rand"
"testing" "testing"
"time" "time"
@ -123,8 +123,8 @@ func TestIPTrackerForceGC(t *testing.T) {
for i := 0; i < 5*max; i++ { for i := 0; i < 5*max; i++ {
e1 := make([]byte, 4) e1 := make([]byte, 4)
e2 := make([]byte, 4) e2 := make([]byte, 4)
mrand.Read(e1) crand.Read(e1)
mrand.Read(e2) crand.Read(e2)
it.AddStatement(string(e1), string(e2)) it.AddStatement(string(e1), string(e2))
it.AddContact(string(e1)) it.AddContact(string(e1))
clock.Run(rate) clock.Run(rate)

View file

@ -29,7 +29,7 @@ var (
const ( const (
VersionMajor = 1 // Major version component of the current release VersionMajor = 1 // Major version component of the current release
VersionMinor = 11 // Minor version component of the current release VersionMinor = 11 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release VersionPatch = 2 // Patch version component of the current release
VersionMeta = "stable" // Version metadata to append to the version string VersionMeta = "stable" // Version metadata to append to the version string
) )

View file

@ -345,7 +345,10 @@ func (c *Client) CallContext(ctx context.Context, result interface{}, method str
case len(resp.Result) == 0: case len(resp.Result) == 0:
return ErrNoResult return ErrNoResult
default: default:
return json.Unmarshal(resp.Result, &result) if result == nil {
return nil
}
return json.Unmarshal(resp.Result, result)
} }
} }

View file

@ -69,6 +69,26 @@ func TestClientResponseType(t *testing.T) {
} }
} }
// This test checks calling a method that returns 'null'.
func TestClientNullResponse(t *testing.T) {
server := newTestServer()
defer server.Stop()
client := DialInProc(server)
defer client.Close()
var result json.RawMessage
if err := client.Call(&result, "test_null"); err != nil {
t.Fatal(err)
}
if result == nil {
t.Fatal("Expected non-nil result")
}
if !reflect.DeepEqual(result, json.RawMessage("null")) {
t.Errorf("Expected null, got %s", result)
}
}
// This test checks that server-returned errors with code and data come out of Client.Call. // This test checks that server-returned errors with code and data come out of Client.Call.
func TestClientErrorData(t *testing.T) { func TestClientErrorData(t *testing.T) {
server := newTestServer() server := newTestServer()

View file

@ -45,7 +45,7 @@ func TestServerRegisterName(t *testing.T) {
t.Fatalf("Expected service calc to be registered") t.Fatalf("Expected service calc to be registered")
} }
wantCallbacks := 12 wantCallbacks := 13
if len(svc.callbacks) != wantCallbacks { if len(svc.callbacks) != wantCallbacks {
t.Errorf("Expected %d callbacks for service 'service', got %d", wantCallbacks, len(svc.callbacks)) t.Errorf("Expected %d callbacks for service 'service', got %d", wantCallbacks, len(svc.callbacks))
} }

View file

@ -78,6 +78,10 @@ func (o *MarshalErrObj) MarshalText() ([]byte, error) {
func (s *testService) NoArgsRets() {} func (s *testService) NoArgsRets() {}
func (s *testService) Null() any {
return nil
}
func (s *testService) Echo(str string, i int, args *echoArgs) echoResult { func (s *testService) Echo(str string, i int, args *echoArgs) echoResult {
return echoResult{str, i, args} return echoResult{str, i, args}
} }

View file

@ -808,7 +808,7 @@ func (db *Database) Update(nodes *MergedNodeSet) error {
if err := rlp.DecodeBytes(n.blob, &account); err != nil { if err := rlp.DecodeBytes(n.blob, &account); err != nil {
return err return err
} }
if account.Root != emptyRoot { if account.Root != types.EmptyRootHash {
db.reference(account.Root, n.parent) db.reference(account.Root, n.parent)
} }
} }

View file

@ -18,6 +18,7 @@ package trie
import ( import (
"bytes" "bytes"
crand "crypto/rand"
"encoding/hex" "encoding/hex"
"math/rand" "math/rand"
"testing" "testing"
@ -97,7 +98,7 @@ func TestHexToCompactInPlaceRandom(t *testing.T) {
for i := 0; i < 10000; i++ { for i := 0; i < 10000; i++ {
l := rand.Intn(128) l := rand.Intn(128)
key := make([]byte, l) key := make([]byte, l)
rand.Read(key) crand.Read(key)
hexBytes := keybytesToHex(key) hexBytes := keybytesToHex(key)
hexOrig := []byte(string(hexBytes)) hexOrig := []byte(string(hexBytes))
exp := hexToCompact(hexBytes) exp := hexToCompact(hexBytes)

View file

@ -22,6 +22,7 @@ import (
"errors" "errors"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
) )
// NodeResolver is used for looking up trie nodes before reaching into the real // NodeResolver is used for looking up trie nodes before reaching into the real
@ -160,7 +161,7 @@ func (e seekError) Error() string {
} }
func newNodeIterator(trie *Trie, start []byte) NodeIterator { func newNodeIterator(trie *Trie, start []byte) NodeIterator {
if trie.Hash() == emptyRoot { if trie.Hash() == types.EmptyRootHash {
return &nodeIterator{ return &nodeIterator{
trie: trie, trie: trie,
err: errIteratorEnd, err: errIteratorEnd,
@ -302,7 +303,7 @@ func (it *nodeIterator) seek(prefix []byte) error {
func (it *nodeIterator) init() (*nodeIteratorState, error) { func (it *nodeIterator) init() (*nodeIteratorState, error) {
root := it.trie.Hash() root := it.trie.Hash()
state := &nodeIteratorState{node: it.trie.root, index: -1} state := &nodeIteratorState{node: it.trie.root, index: -1}
if root != emptyRoot { if root != types.EmptyRootHash {
state.hash = root state.hash = root
} }
return state, state.resolve(it, nil) return state, state.resolve(it, nil)

View file

@ -23,7 +23,6 @@ import (
mrand "math/rand" mrand "math/rand"
"sort" "sort"
"testing" "testing"
"time"
"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"
@ -31,10 +30,6 @@ import (
"github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/ethdb/memorydb"
) )
func init() {
mrand.Seed(time.Now().Unix())
}
// makeProvers creates Merkle trie provers based on different implementations to // makeProvers creates Merkle trie provers based on different implementations to
// test all variations. // test all variations.
func makeProvers(trie *Trie) []func(key []byte) *memorydb.Database { func makeProvers(trie *Trie) []func(key []byte) *memorydb.Database {

View file

@ -25,6 +25,7 @@ import (
"sync" "sync"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
@ -407,7 +408,7 @@ func (st *StackTrie) hashRec(hasher *hasher, path []byte) {
return return
case emptyNode: case emptyNode:
st.val = emptyRoot.Bytes() st.val = types.EmptyRootHash.Bytes()
st.key = st.key[:0] st.key = st.key[:0]
st.nodeType = hashedNode st.nodeType = hashedNode
return return

View file

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/prque" "github.com/ethereum/go-ethereum/common/prque"
"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/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
@ -184,7 +185,7 @@ func NewSync(root common.Hash, database ethdb.KeyValueReader, callback LeafCallb
// hex format and contain all the parent path if it's layered trie node. // hex format and contain all the parent path if it's layered trie node.
func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, parentPath []byte, callback LeafCallback) { func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, parentPath []byte, callback LeafCallback) {
// Short circuit if the trie is empty or already known // Short circuit if the trie is empty or already known
if root == emptyRoot { if root == types.EmptyRootHash {
return return
} }
if s.membatch.hasNode(path) { if s.membatch.hasNode(path) {
@ -217,7 +218,7 @@ func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, par
// as is. // as is.
func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) { func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) {
// Short circuit if the entry is empty or already known // Short circuit if the entry is empty or already known
if hash == emptyState { if hash == types.EmptyCodeHash {
return return
} }
if s.membatch.hasCode(hash) { if s.membatch.hasCode(hash) {

View file

@ -23,6 +23,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/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/ethdb/memorydb"
) )
@ -104,7 +105,7 @@ func TestEmptySync(t *testing.T) {
dbA := NewDatabase(rawdb.NewMemoryDatabase()) dbA := NewDatabase(rawdb.NewMemoryDatabase())
dbB := NewDatabase(rawdb.NewMemoryDatabase()) dbB := NewDatabase(rawdb.NewMemoryDatabase())
emptyA, _ := New(TrieID(common.Hash{}), dbA) emptyA, _ := New(TrieID(common.Hash{}), dbA)
emptyB, _ := New(TrieID(emptyRoot), dbB) emptyB, _ := New(TrieID(types.EmptyRootHash), dbB)
for i, trie := range []*Trie{emptyA, emptyB} { for i, trie := range []*Trie{emptyA, emptyB} {
sync := NewSync(trie.Hash(), memorydb.New(), nil, []*Database{dbA, dbB}[i].Scheme()) sync := NewSync(trie.Hash(), memorydb.New(), nil, []*Database{dbA, dbB}[i].Scheme())

View file

@ -23,18 +23,10 @@ import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
var (
// emptyRoot is the known root hash of an empty trie.
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
// emptyState is the known hash of an empty state trie entry.
emptyState = crypto.Keccak256Hash(nil)
)
// Trie is a Merkle Patricia Trie. Use New to create a trie that sits on // Trie is a Merkle Patricia Trie. Use New to create a trie that sits on
// top of a database. Whenever trie performs a commit operation, the generated // top of a database. Whenever trie performs a commit operation, the generated
// nodes will be gathered and returned in a set. Once the trie is committed, // nodes will be gathered and returned in a set. Once the trie is committed,
@ -91,7 +83,7 @@ func New(id *ID, db NodeReader) (*Trie, error) {
reader: reader, reader: reader,
//tracer: newTracer(), //tracer: newTracer(),
} }
if id.Root != (common.Hash{}) && id.Root != emptyRoot { if id.Root != (common.Hash{}) && id.Root != types.EmptyRootHash {
rootnode, err := trie.resolveAndTrack(id.Root[:], nil) rootnode, err := trie.resolveAndTrack(id.Root[:], nil)
if err != nil { if err != nil {
return nil, err return nil, err
@ -576,7 +568,7 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *NodeSet) {
// Wrap tracked deletions as the return // Wrap tracked deletions as the return
set := NewNodeSet(t.owner) set := NewNodeSet(t.owner)
t.tracer.markDeletions(set) t.tracer.markDeletions(set)
return emptyRoot, set return types.EmptyRootHash, set
} }
// Derive the hash for all dirty nodes first. We hold the assumption // Derive the hash for all dirty nodes first. We hold the assumption
// in the following procedure that all nodes are hashed. // in the following procedure that all nodes are hashed.
@ -599,7 +591,7 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *NodeSet) {
// hashRoot calculates the root hash of the given trie // hashRoot calculates the root hash of the given trie
func (t *Trie) hashRoot() (node, node, error) { func (t *Trie) hashRoot() (node, node, error) {
if t.root == nil { if t.root == nil {
return hashNode(emptyRoot.Bytes()), nil, nil return hashNode(types.EmptyRootHash.Bytes()), nil, nil
} }
// If the number of changes is below 100, we let one thread handle it // If the number of changes is below 100, we let one thread handle it
h := newHasher(t.unhashed >= 100) h := newHasher(t.unhashed >= 100)

View file

@ -18,6 +18,7 @@ package trie
import ( import (
"bytes" "bytes"
crand "crypto/rand"
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
@ -46,7 +47,7 @@ func init() {
func TestEmptyTrie(t *testing.T) { func TestEmptyTrie(t *testing.T) {
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase())) trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase()))
res := trie.Hash() res := trie.Hash()
exp := emptyRoot exp := types.EmptyRootHash
if res != exp { if res != exp {
t.Errorf("expected %x got %x", exp, res) t.Errorf("expected %x got %x", exp, res)
} }
@ -430,7 +431,7 @@ func runRandTest(rt randTest) bool {
} }
case opProve: case opProve:
hash := tr.Hash() hash := tr.Hash()
if hash == emptyRoot { if hash == types.EmptyRootHash {
continue continue
} }
proofDb := rawdb.NewMemoryDatabase() proofDb := rawdb.NewMemoryDatabase()
@ -717,7 +718,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
for i := 0; i < len(accounts); i++ { for i := 0; i < len(accounts); i++ {
var ( var (
nonce = uint64(random.Int63()) nonce = uint64(random.Int63())
root = emptyRoot root = types.EmptyRootHash
code = crypto.Keccak256(nil) code = crypto.Keccak256(nil)
) )
// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems, // The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
@ -1127,8 +1128,8 @@ func TestDecodeNode(t *testing.T) {
elems = make([]byte, 20) elems = make([]byte, 20)
) )
for i := 0; i < 5000000; i++ { for i := 0; i < 5000000; i++ {
rand.Read(hash) crand.Read(hash)
rand.Read(elems) crand.Read(elems)
decodeNode(hash, elems) decodeNode(hash, elems)
} }
} }

View file

@ -22,6 +22,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"
) )
// Tests if the trie diffs are tracked correctly. // Tests if the trie diffs are tracked correctly.
@ -286,7 +287,7 @@ func TestDeleteAll(t *testing.T) {
trie.Delete([]byte(val.k)) trie.Delete([]byte(val.k))
} }
root, set = trie.Commit(false) root, set = trie.Commit(false)
if root != emptyRoot { if root != types.EmptyRootHash {
t.Fatalf("Invalid trie root %v", root) t.Fatalf("Invalid trie root %v", root)
} }
for path, blob := range set.deletes { for path, blob := range set.deletes {