Merge remote-tracking branch 'origin/develop' into feature/trie_interval_clone
This commit is contained in:
commit
50a295b789
@ -74,12 +74,11 @@ var (
|
||||
// - newPayloadV1: if the payload was accepted, but not processed (side chain)
|
||||
ACCEPTED = "ACCEPTED"
|
||||
|
||||
INVALIDBLOCKHASH = "INVALID_BLOCK_HASH"
|
||||
|
||||
GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"}
|
||||
UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"}
|
||||
InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"}
|
||||
InvalidPayloadAttributes = &EngineAPIError{code: -38003, msg: "Invalid payload attributes"}
|
||||
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
|
||||
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
|
||||
|
||||
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
|
||||
|
@ -41,3 +41,6 @@ c4f58b7e227b9fd41f0e9310dc83f4a4e7d026598e2f6e95b78761081a6d9bd2 golangci-lint-
|
||||
eb57f9bcb56646f2e3d6ccaf02ec227815fb05077b2e0b1bf9e755805acdc2b9 golangci-lint-1.51.1-windows-arm64.zip
|
||||
bce02f7232723cb727755ee11f168a700a00896a25d37f87c4b173bce55596b4 golangci-lint-1.51.1-windows-armv6.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
|
||||
|
47
build/ci.go
47
build/ci.go
@ -128,7 +128,7 @@ var (
|
||||
"focal": "golang-go", // EOL: 04/2030
|
||||
"jammy": "golang-go", // EOL: 04/2032
|
||||
"kinetic": "golang-go", // EOL: 07/2023
|
||||
//"lunar": "golang-go", // EOL: 01/2024
|
||||
"lunar": "golang-go", // EOL: 01/2024
|
||||
}
|
||||
|
||||
debGoBootPaths = map[string]string{
|
||||
@ -136,10 +136,18 @@ var (
|
||||
"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
|
||||
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"))
|
||||
@ -655,10 +663,11 @@ func doDebianSource(cmdline []string) {
|
||||
gpg.Stdin = bytes.NewReader(key)
|
||||
build.MustRun(gpg)
|
||||
}
|
||||
|
||||
// Download and verify the Go source package.
|
||||
gobundle := downloadGoSources(*cachedir)
|
||||
|
||||
// Download and verify the Go source packages.
|
||||
var (
|
||||
gobootbundle = downloadGoBootstrapSources(*cachedir)
|
||||
gobundle = downloadGoSources(*cachedir)
|
||||
)
|
||||
// Download all the dependencies needed to build the sources and run the ci script
|
||||
srcdepfetch := tc.Go("mod", "download")
|
||||
srcdepfetch.Env = append(srcdepfetch.Env, "GOPATH="+filepath.Join(*workdir, "modgopath"))
|
||||
@ -675,12 +684,19 @@ func doDebianSource(cmdline []string) {
|
||||
meta := newDebMetadata(distro, goboot, *signer, env, now, pkg.Name, pkg.Version, pkg.Executables)
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
os.MkdirAll(filepath.Join(pkgdir, ".mod", "cache"), 0755)
|
||||
@ -709,6 +725,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.
|
||||
func downloadGoSources(cachedir string) string {
|
||||
csdb := build.MustLoadChecksums("build/checksums.txt")
|
||||
|
@ -16,7 +16,11 @@ override_dh_auto_build:
|
||||
# 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
|
||||
# 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
|
||||
# entire dependency source cache with go-ethereum.
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth/protocols/snap"
|
||||
"github.com/ethereum/go-ethereum/internal/utesting"
|
||||
@ -210,13 +211,6 @@ type byteCodesTest struct {
|
||||
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.
|
||||
func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
|
||||
// The halfchain import should yield these bytecodes
|
||||
@ -263,15 +257,15 @@ func (s *Suite) TestSnapGetByteCodes(t *utesting.T) {
|
||||
},
|
||||
// Empties
|
||||
{
|
||||
nBytes: 10000, hashes: []common.Hash{emptyRoot},
|
||||
nBytes: 10000, hashes: []common.Hash{types.EmptyRootHash},
|
||||
expHashes: 0,
|
||||
},
|
||||
{
|
||||
nBytes: 10000, hashes: []common.Hash{emptyCode},
|
||||
nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash},
|
||||
expHashes: 1,
|
||||
},
|
||||
{
|
||||
nBytes: 10000, hashes: []common.Hash{emptyCode, emptyCode, emptyCode},
|
||||
nBytes: 10000, hashes: []common.Hash{types.EmptyCodeHash, types.EmptyCodeHash, types.EmptyCodeHash},
|
||||
expHashes: 3,
|
||||
},
|
||||
// The existing bytecodes
|
||||
@ -363,7 +357,7 @@ func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
|
||||
for i := 1; i <= 65; i++ {
|
||||
accPaths = append(accPaths, pathTo(i))
|
||||
}
|
||||
empty := emptyCode
|
||||
empty := types.EmptyCodeHash
|
||||
for i, tc := range []trieNodesTest{
|
||||
{
|
||||
root: s.chain.RootAt(999),
|
||||
|
@ -120,8 +120,8 @@ func (i *bbInput) ToBlock() *types.Block {
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
Coinbase: common.Address{},
|
||||
Root: i.Header.Root,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
Bloom: i.Header.Bloom,
|
||||
Difficulty: common.Big0,
|
||||
Number: i.Header.Number,
|
||||
|
@ -47,10 +47,10 @@ var (
|
||||
dumpConfigCommand = &cli.Command{
|
||||
Action: dumpConfig,
|
||||
Name: "dumpconfig",
|
||||
Usage: "Show configuration values",
|
||||
ArgsUsage: "",
|
||||
Usage: "Export configuration values in a TOML format",
|
||||
ArgsUsage: "<dumpfile (optional)>",
|
||||
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{
|
||||
|
@ -38,14 +38,6 @@ import (
|
||||
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 (
|
||||
snapshotCommand = &cli.Command{
|
||||
Name: "snapshot",
|
||||
@ -308,7 +300,7 @@ func traverseState(ctx *cli.Context) error {
|
||||
log.Error("Invalid account encountered during traversal", "err", err)
|
||||
return err
|
||||
}
|
||||
if acc.Root != emptyRoot {
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(accIter.Key), acc.Root)
|
||||
storageTrie, err := trie.NewStateTrie(id, triedb)
|
||||
if err != nil {
|
||||
@ -324,7 +316,7 @@ func traverseState(ctx *cli.Context) error {
|
||||
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)) {
|
||||
log.Error("Code is missing", "hash", common.BytesToHash(acc.CodeHash))
|
||||
return errors.New("missing code")
|
||||
@ -423,7 +415,7 @@ func traverseRawState(ctx *cli.Context) error {
|
||||
log.Error("Invalid account encountered during traversal", "err", err)
|
||||
return errors.New("invalid account")
|
||||
}
|
||||
if acc.Root != emptyRoot {
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(accIter.LeafKey()), acc.Root)
|
||||
storageTrie, err := trie.NewStateTrie(id, triedb)
|
||||
if err != nil {
|
||||
@ -461,7 +453,7 @@ func traverseRawState(ctx *cli.Context) 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)) {
|
||||
log.Error("Code is missing", "account", common.BytesToHash(accIter.LeafKey()))
|
||||
return errors.New("missing code")
|
||||
@ -536,7 +528,7 @@ func dumpState(ctx *cli.Context) error {
|
||||
CodeHash: account.CodeHash,
|
||||
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))
|
||||
}
|
||||
if !conf.SkipStorage {
|
||||
|
@ -49,6 +49,17 @@ func NewHexOrDecimal256(x int64) *HexOrDecimal256 {
|
||||
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.
|
||||
func (i *HexOrDecimal256) UnmarshalText(input []byte) error {
|
||||
bigint, ok := ParseBig256(string(input))
|
||||
|
@ -41,6 +41,17 @@ const (
|
||||
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
||||
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.
|
||||
func (i *HexOrDecimal64) UnmarshalText(input []byte) error {
|
||||
int, ok := ParseUint64(string(input))
|
||||
|
@ -709,11 +709,11 @@ func TestConcurrentDiskCacheGeneration(t *testing.T) {
|
||||
block := types.NewBlockWithHeader(&types.Header{
|
||||
Number: big.NewInt(3311058),
|
||||
ParentHash: common.HexToHash("0xd783efa4d392943503f28438ad5830b2d5964696ffc285f338585e9fe0a37a05"),
|
||||
UncleHash: common.HexToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
Coinbase: common.HexToAddress("0xc0ea08a2d404d3172d2add29a45be56da40e2949"),
|
||||
Root: common.HexToHash("0x77d14e10470b5850332524f8cd6f69ad21f070ce92dca33ab2858300242ef2f1"),
|
||||
TxHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
|
||||
ReceiptHash: common.HexToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"),
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
Difficulty: big.NewInt(167925187834220),
|
||||
GasLimit: 4015682,
|
||||
GasUsed: 0,
|
||||
|
@ -252,8 +252,8 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
|
||||
ParentHash: hash,
|
||||
Difficulty: big.NewInt(1),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
}
|
||||
hash = header.Hash()
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||
if stats.ignored > 0 {
|
||||
context = append(context, []interface{}{"ignored", stats.ignored}...)
|
||||
}
|
||||
log.Info("Imported new block receipts", context...)
|
||||
log.Debug("Imported new block receipts", context...)
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
|
||||
// flush is very similar with deriveHash, but the main difference is
|
||||
// all the generated states will be persisted into the given database.
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -166,15 +166,15 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rawdb.WriteGenesisStateSpec(db, root, blob)
|
||||
rawdb.WriteGenesisStateSpec(db, blockhash, blob)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CommitGenesisState loads the stored genesis state with the given block
|
||||
// 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
|
||||
blob := rawdb.ReadGenesisStateSpec(db, hash)
|
||||
blob := rawdb.ReadGenesisStateSpec(db, blockhash)
|
||||
if len(blob) != 0 {
|
||||
if err := alloc.UnmarshalJSON(blob); err != nil {
|
||||
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
|
||||
// - private network, can't recover
|
||||
var genesis *Genesis
|
||||
switch hash {
|
||||
switch blockhash {
|
||||
case params.MainnetGenesisHash:
|
||||
genesis = DefaultGenesisBlock()
|
||||
case params.RinkebyGenesisHash:
|
||||
@ -202,7 +202,7 @@ func CommitGenesisState(db ethdb.Database, triedb *trie.Database, hash common.Ha
|
||||
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.
|
||||
@ -467,7 +467,7 @@ func (g *Genesis) ToBlock() *types.Block {
|
||||
}
|
||||
var withdrawals []*types.Withdrawal
|
||||
if g.Config != nil && g.Config.IsShanghai(g.Timestamp) {
|
||||
head.WithdrawalsHash = &types.EmptyRootHash
|
||||
head.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||
withdrawals = make([]*types.Withdrawal, 0)
|
||||
}
|
||||
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
|
||||
// specification as well as the specification itself into the provided
|
||||
// database.
|
||||
if err := g.Alloc.flush(db, triedb); err != nil {
|
||||
if err := g.Alloc.flush(db, triedb, block.Hash()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
|
||||
|
@ -389,7 +389,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, start time.Time,
|
||||
if res.ignored > 0 {
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -251,9 +251,10 @@ func (mt *metaTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, sc
|
||||
tracer.CaptureFault(pc, core.OpCode(op), gas, cost, wrappers.NewWrappedScopeContext(scope), depth, err)
|
||||
}
|
||||
}
|
||||
// passing zero as a dummy value is foundation PluGeth only, it is being done to preserve compatability with other networks
|
||||
func (mt *metaTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||
for _, tracer := range mt.tracers {
|
||||
tracer.CaptureEnd(output, gasUsed, err)
|
||||
tracer.CaptureEnd(output, gasUsed, 0, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ import (
|
||||
func ReadCanonicalHash(db ethdb.Reader, number uint64) common.Hash {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(chainFreezerHashTable, number)
|
||||
data, _ = reader.Ancient(ChainFreezerHashTable, number)
|
||||
if len(data) == 0 {
|
||||
// Get it by hash from leveldb
|
||||
data, _ = db.Get(headerHashKey(number))
|
||||
@ -334,7 +334,7 @@ func ReadHeaderRange(db ethdb.Reader, number uint64, count uint64) []rlp.RawValu
|
||||
}
|
||||
// read remaining from ancients
|
||||
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 {
|
||||
// the data is on the order [h, h+1, .., n] -- reordering needed
|
||||
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
|
||||
// comparison is necessary since ancient database only maintains
|
||||
// the canonical data.
|
||||
data, _ = reader.Ancient(chainFreezerHeaderTable, number)
|
||||
data, _ = reader.Ancient(ChainFreezerHeaderTable, number)
|
||||
if len(data) > 0 && crypto.Keccak256Hash(data) == hash {
|
||||
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
|
||||
// is part of the ancient (canon) set.
|
||||
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 {
|
||||
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 {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(chainFreezerBodiesTable, number)
|
||||
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
||||
return nil
|
||||
}
|
||||
// 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 {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(chainFreezerBodiesTable, number)
|
||||
data, _ = reader.Ancient(ChainFreezerBodiesTable, number)
|
||||
if len(data) > 0 {
|
||||
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 {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(chainFreezerDifficultyTable, number)
|
||||
data, _ = reader.Ancient(ChainFreezerDifficultyTable, number)
|
||||
return nil
|
||||
}
|
||||
// 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 {
|
||||
// Check if the data is in ancients
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(chainFreezerReceiptTable, number)
|
||||
data, _ = reader.Ancient(ChainFreezerReceiptTable, number)
|
||||
return nil
|
||||
}
|
||||
// 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 {
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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 nil
|
||||
|
@ -113,8 +113,8 @@ func TestBlockStorage(t *testing.T) {
|
||||
block := types.NewBlockWithHeader(&types.Header{
|
||||
Extra: []byte("test block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
if entry := ReadBlock(db, block.Hash(), block.NumberU64()); entry != nil {
|
||||
t.Fatalf("Non existent block returned: %v", entry)
|
||||
@ -161,8 +161,8 @@ func TestPartialBlockStorage(t *testing.T) {
|
||||
block := types.NewBlockWithHeader(&types.Header{
|
||||
Extra: []byte("test block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
// Store a header and check that it's not recognized as a block
|
||||
WriteHeader(db, block.Header())
|
||||
@ -198,8 +198,8 @@ func TestBadBlockStorage(t *testing.T) {
|
||||
Number: big.NewInt(1),
|
||||
Extra: []byte("bad block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
if entry := ReadBadBlock(db, block.Hash()); entry != nil {
|
||||
t.Fatalf("Non existent block returned: %v", entry)
|
||||
@ -216,8 +216,8 @@ func TestBadBlockStorage(t *testing.T) {
|
||||
Number: big.NewInt(2),
|
||||
Extra: []byte("bad block two"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
WriteBadBlock(db, blockTwo)
|
||||
|
||||
@ -235,8 +235,8 @@ func TestBadBlockStorage(t *testing.T) {
|
||||
Number: big.NewInt(int64(n)),
|
||||
Extra: []byte("bad block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
WriteBadBlock(db, block)
|
||||
}
|
||||
@ -446,8 +446,8 @@ func TestAncientStorage(t *testing.T) {
|
||||
Number: big.NewInt(0),
|
||||
Extra: []byte("test block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
// Ensure nothing non-existent will be read
|
||||
hash, number := block.Hash(), block.NumberU64()
|
||||
@ -889,8 +889,8 @@ func TestHeadersRLPStorage(t *testing.T) {
|
||||
Number: big.NewInt(int64(i)),
|
||||
Extra: []byte("test block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
ParentHash: pHash,
|
||||
})
|
||||
chain = append(chain, block)
|
||||
|
@ -82,15 +82,15 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
|
||||
}
|
||||
|
||||
// ReadGenesisStateSpec retrieves the genesis state specification based on the
|
||||
// given genesis hash.
|
||||
func ReadGenesisStateSpec(db ethdb.KeyValueReader, hash common.Hash) []byte {
|
||||
data, _ := db.Get(genesisStateSpecKey(hash))
|
||||
// given genesis (block-)hash.
|
||||
func ReadGenesisStateSpec(db ethdb.KeyValueReader, blockhash common.Hash) []byte {
|
||||
data, _ := db.Get(genesisStateSpecKey(blockhash))
|
||||
return data
|
||||
}
|
||||
|
||||
// WriteGenesisStateSpec writes the genesis state specification into the disk.
|
||||
func WriteGenesisStateSpec(db ethdb.KeyValueWriter, hash common.Hash, data []byte) {
|
||||
if err := db.Put(genesisStateSpecKey(hash), data); err != nil {
|
||||
func WriteGenesisStateSpec(db ethdb.KeyValueWriter, blockhash common.Hash, data []byte) {
|
||||
if err := db.Put(genesisStateSpecKey(blockhash), data); err != nil {
|
||||
log.Crit("Failed to store genesis state", "err", err)
|
||||
}
|
||||
}
|
||||
|
@ -18,30 +18,30 @@ package rawdb
|
||||
|
||||
// The list of table names of chain freezer.
|
||||
const (
|
||||
// chainFreezerHeaderTable indicates the name of the freezer header table.
|
||||
chainFreezerHeaderTable = "headers"
|
||||
// ChainFreezerHeaderTable indicates the name of the freezer header table.
|
||||
ChainFreezerHeaderTable = "headers"
|
||||
|
||||
// chainFreezerHashTable indicates the name of the freezer canonical hash table.
|
||||
chainFreezerHashTable = "hashes"
|
||||
// ChainFreezerHashTable indicates the name of the freezer canonical hash table.
|
||||
ChainFreezerHashTable = "hashes"
|
||||
|
||||
// chainFreezerBodiesTable indicates the name of the freezer block body table.
|
||||
chainFreezerBodiesTable = "bodies"
|
||||
// ChainFreezerBodiesTable indicates the name of the freezer block body table.
|
||||
ChainFreezerBodiesTable = "bodies"
|
||||
|
||||
// chainFreezerReceiptTable indicates the name of the freezer receipts table.
|
||||
chainFreezerReceiptTable = "receipts"
|
||||
// ChainFreezerReceiptTable indicates the name of the freezer receipts table.
|
||||
ChainFreezerReceiptTable = "receipts"
|
||||
|
||||
// chainFreezerDifficultyTable indicates the name of the freezer total difficulty table.
|
||||
chainFreezerDifficultyTable = "diffs"
|
||||
// ChainFreezerDifficultyTable indicates the name of the freezer total difficulty table.
|
||||
ChainFreezerDifficultyTable = "diffs"
|
||||
)
|
||||
|
||||
// chainFreezerNoSnappy configures whether compression is disabled for the ancient-tables.
|
||||
// Hashes and difficulties don't compress well.
|
||||
var chainFreezerNoSnappy = map[string]bool{
|
||||
chainFreezerHeaderTable: false,
|
||||
chainFreezerHashTable: true,
|
||||
chainFreezerBodiesTable: false,
|
||||
chainFreezerReceiptTable: false,
|
||||
chainFreezerDifficultyTable: true,
|
||||
ChainFreezerHeaderTable: false,
|
||||
ChainFreezerHashTable: true,
|
||||
ChainFreezerBodiesTable: false,
|
||||
ChainFreezerReceiptTable: false,
|
||||
ChainFreezerDifficultyTable: true,
|
||||
}
|
||||
|
||||
// The list of identifiers of ancient stores.
|
||||
|
@ -55,8 +55,8 @@ type chainFreezer struct {
|
||||
}
|
||||
|
||||
// newChainFreezer initializes the freezer for ancient chain data.
|
||||
func newChainFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*chainFreezer, error) {
|
||||
freezer, err := NewFreezer(datadir, namespace, readonly, maxTableSize, tables)
|
||||
func newChainFreezer(datadir string, namespace string, readonly bool) (*chainFreezer, error) {
|
||||
freezer, err := NewChainFreezer(datadir, namespace, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -280,19 +280,19 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
||||
if i+count > frozen {
|
||||
count = frozen - i
|
||||
}
|
||||
data, err := db.AncientRange(chainFreezerHashTable, i, count, 32*count)
|
||||
data, err := db.AncientRange(ChainFreezerHashTable, i, count, 32*count)
|
||||
if err != nil {
|
||||
log.Crit("Failed to init database from freezer", "err", err)
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ func resolveChainFreezerDir(ancient string) string {
|
||||
// where the chain freezer can be opened.
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace string, readonly bool) (ethdb.Database, error) {
|
||||
// Create the idle freezer instance
|
||||
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
|
||||
frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -231,7 +231,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, ancient string, namespace st
|
||||
// If the freezer already contains something, ensure that the genesis blocks
|
||||
// match, otherwise we might mix up freezers across chains and destroy both
|
||||
// the freezer and the key-value store.
|
||||
frgenesis, err := frdb.Ancient(chainFreezerHashTable, 0)
|
||||
frgenesis, err := frdb.Ancient(ChainFreezerHashTable, 0)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
|
||||
} else if !bytes.Equal(kvgenesis, frgenesis) {
|
||||
|
@ -79,6 +79,12 @@ type Freezer struct {
|
||||
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
|
||||
// data according to the given parameters.
|
||||
//
|
||||
|
@ -26,12 +26,18 @@ import (
|
||||
"path"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// seeding random below, as well as the time import are PluGeth injections to enable this test to pass as it fails in geth v1.11.1
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
var freezerTestTableDef = map[string]bool{"test": true}
|
||||
|
||||
func TestFreezerModify(t *testing.T) {
|
||||
|
@ -70,7 +70,7 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
receipts []byte
|
||||
td []byte
|
||||
)
|
||||
if hashi, ok := update[chainFreezerHashTable]; ok {
|
||||
if hashi, ok := update[ChainFreezerHashTable]; ok {
|
||||
switch v := hashi.(type) {
|
||||
case []byte:
|
||||
hash = v
|
||||
@ -78,7 +78,7 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
hash, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if headeri, ok := update[chainFreezerHeaderTable]; ok {
|
||||
if headeri, ok := update[ChainFreezerHeaderTable]; ok {
|
||||
switch v := headeri.(type) {
|
||||
case []byte:
|
||||
header = v
|
||||
@ -86,7 +86,7 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
header, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if bodyi, ok := update[chainFreezerBodiesTable]; ok {
|
||||
if bodyi, ok := update[ChainFreezerBodiesTable]; ok {
|
||||
switch v := bodyi.(type) {
|
||||
case []byte:
|
||||
body = v
|
||||
@ -94,7 +94,7 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
body, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if receiptsi, ok := update[chainFreezerReceiptTable]; ok {
|
||||
if receiptsi, ok := update[ChainFreezerReceiptTable]; ok {
|
||||
switch v := receiptsi.(type) {
|
||||
case []byte:
|
||||
receipts = v
|
||||
@ -102,7 +102,7 @@ func PluginCommitUpdate(pl *plugins.PluginLoader, num uint64) {
|
||||
receipts, _ = rlp.EncodeToBytes(v)
|
||||
}
|
||||
}
|
||||
if tdi, ok := update[chainFreezerDifficultyTable]; ok {
|
||||
if tdi, ok := update[ChainFreezerDifficultyTable]; ok {
|
||||
switch v := tdi.(type) {
|
||||
case []byte:
|
||||
td = v
|
||||
|
@ -117,7 +117,7 @@ func (it *NodeIterator) step() error {
|
||||
if !it.dataIt.Next(true) {
|
||||
it.dataIt = nil
|
||||
}
|
||||
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
|
||||
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||
it.codeHash = common.BytesToHash(account.CodeHash)
|
||||
addrHash := common.BytesToHash(it.stateIt.LeafKey())
|
||||
it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash))
|
||||
|
@ -31,7 +31,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@ -55,14 +54,6 @@ const (
|
||||
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.
|
||||
type Config struct {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
if acc.Root != emptyRoot {
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(genesis.Root(), common.BytesToHash(accIter.LeafKey()), acc.Root)
|
||||
storageTrie, err := trie.NewStateTrie(id, trie.NewDatabase(db))
|
||||
if err != nil {
|
||||
@ -463,7 +454,7 @@ func extractGenesis(db ethdb.Database, stateBloom *stateBloom) error {
|
||||
return storageIter.Error()
|
||||
}
|
||||
}
|
||||
if !bytes.Equal(acc.CodeHash, emptyCode) {
|
||||
if !bytes.Equal(acc.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||
stateBloom.Put(acc.CodeHash, nil)
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
@ -41,10 +42,10 @@ func SlimAccount(nonce uint64, balance *big.Int, root common.Hash, codehash []by
|
||||
Nonce: nonce,
|
||||
Balance: balance,
|
||||
}
|
||||
if root != emptyRoot {
|
||||
if root != types.EmptyRootHash {
|
||||
slim.Root = root[:]
|
||||
}
|
||||
if !bytes.Equal(codehash, emptyCode[:]) {
|
||||
if !bytes.Equal(codehash, types.EmptyCodeHash[:]) {
|
||||
slim.CodeHash = codehash
|
||||
}
|
||||
return slim
|
||||
@ -68,10 +69,10 @@ func FullAccount(data []byte) (Account, error) {
|
||||
return Account{}, err
|
||||
}
|
||||
if len(account.Root) == 0 {
|
||||
account.Root = emptyRoot[:]
|
||||
account.Root = types.EmptyRootHash[:]
|
||||
}
|
||||
if len(account.CodeHash) == 0 {
|
||||
account.CodeHash = emptyCode[:]
|
||||
account.CodeHash = types.EmptyCodeHash[:]
|
||||
}
|
||||
return account, nil
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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/log"
|
||||
"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()
|
||||
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.
|
||||
if codeHash != emptyCode {
|
||||
if codeHash != types.EmptyCodeHash {
|
||||
code := rawdb.ReadCode(src, codeHash)
|
||||
if len(code) == 0 {
|
||||
return common.Hash{}, errors.New("failed to read contract code")
|
||||
|
@ -27,7 +27,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"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/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@ -35,12 +35,6 @@ import (
|
||||
)
|
||||
|
||||
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
|
||||
// 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,
|
||||
@ -591,10 +585,10 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er
|
||||
if accMarker == nil || !bytes.Equal(account[:], accMarker) {
|
||||
dataLen := len(val) // Approximate size, saves us a round of RLP-encoding
|
||||
if !write {
|
||||
if bytes.Equal(acc.CodeHash, emptyCode[:]) {
|
||||
if bytes.Equal(acc.CodeHash, types.EmptyCodeHash[:]) {
|
||||
dataLen -= 32
|
||||
}
|
||||
if acc.Root == emptyRoot {
|
||||
if acc.Root == types.EmptyRootHash {
|
||||
dataLen -= 32
|
||||
}
|
||||
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
|
||||
// verify or regenerate the contract storage.
|
||||
if acc.Root == emptyRoot {
|
||||
if acc.Root == types.EmptyRootHash {
|
||||
ctx.removeStorageAt(account)
|
||||
} else {
|
||||
var storeMarker []byte
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
@ -49,9 +50,9 @@ func TestGeneration(t *testing.T) {
|
||||
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)
|
||||
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()})
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), 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: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.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-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()
|
||||
|
||||
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.addSnapAccount("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: types.EmptyCodeHash.Bytes()})
|
||||
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.addSnapAccount("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: 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)
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addSnapAccount("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: types.EmptyCodeHash.Bytes()})
|
||||
helper.addSnapStorage("acc-3", []string{"key-1", "key-2", "key-3"}, []string{"val-1", "val-2", "val-3"})
|
||||
|
||||
root, snap := helper.CommitAndGenerate()
|
||||
@ -235,28 +236,28 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
helper := newHelper()
|
||||
|
||||
// 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"})
|
||||
|
||||
// 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)
|
||||
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
|
||||
{
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
}
|
||||
|
||||
@ -264,22 +265,22 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
{
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
}
|
||||
|
||||
@ -287,17 +288,17 @@ func TestGenerateExistentStateWithWrongStorage(t *testing.T) {
|
||||
{
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
|
||||
// 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.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"})
|
||||
}
|
||||
|
||||
@ -337,25 +338,25 @@ func TestGenerateExistentStateWithWrongAccounts(t *testing.T) {
|
||||
|
||||
// Missing accounts, only in the trie
|
||||
{
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Beginning
|
||||
helper.addTrieAccount("acc-4", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // Middle
|
||||
helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // End
|
||||
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: types.EmptyCodeHash.Bytes()}) // Middle
|
||||
helper.addTrieAccount("acc-6", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: types.EmptyCodeHash.Bytes()}) // End
|
||||
}
|
||||
|
||||
// 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.addTrieAccount("acc-3", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addSnapAccount("acc-3", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), 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: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()})
|
||||
}
|
||||
|
||||
// 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-5", &Account{Balance: big.NewInt(1), Root: emptyRoot.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-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: types.EmptyRootHash.Bytes(), CodeHash: common.Hex2Bytes("0x1234")}) // Middle
|
||||
helper.addSnapAccount("acc-7", &Account{Balance: big.NewInt(1), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // after the end
|
||||
}
|
||||
|
||||
root, snap := helper.CommitAndGenerate()
|
||||
@ -384,9 +385,9 @@ func TestGenerateCorruptAccountTrie(t *testing.T) {
|
||||
// without any storage slots to keep the test smaller.
|
||||
helper := newHelper()
|
||||
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
|
||||
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: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
helper.addTrieAccount("acc-3", &Account{Balance: big.NewInt(3), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
|
||||
|
||||
root := helper.Commit() // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
|
||||
|
||||
@ -419,10 +420,10 @@ func TestGenerateMissingStorageTrie(t *testing.T) {
|
||||
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
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
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: 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)
|
||||
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()
|
||||
|
||||
@ -453,10 +454,10 @@ func TestGenerateCorruptStorageTrie(t *testing.T) {
|
||||
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
|
||||
helper.addTrieAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()}) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
helper.addTrieAccount("acc-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
|
||||
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: 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)
|
||||
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()
|
||||
|
||||
@ -488,7 +489,7 @@ func TestGenerateWithExtraAccounts(t *testing.T) {
|
||||
[]string{"val-1", "val-2", "val-3", "val-4", "val-5"},
|
||||
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)
|
||||
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"},
|
||||
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)
|
||||
key := hashData([]byte("acc-2"))
|
||||
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
|
||||
@ -559,7 +560,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) {
|
||||
[]string{"val-1", "val-2", "val-3"},
|
||||
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)
|
||||
helper.accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
|
||||
|
||||
@ -573,8 +574,7 @@ func TestGenerateWithManyExtraAccounts(t *testing.T) {
|
||||
{
|
||||
// 100 accounts exist only in snapshot
|
||||
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: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
|
||||
acc := &Account{Balance: big.NewInt(int64(i)), Root: types.EmptyRootHash.Bytes(), CodeHash: types.EmptyCodeHash.Bytes()}
|
||||
val, _ := rlp.EncodeToBytes(acc)
|
||||
key := hashData([]byte(fmt.Sprintf("acc-%d", i)))
|
||||
rawdb.WriteAccountSnapshot(helper.diskdb, key, val)
|
||||
@ -611,7 +611,7 @@ func TestGenerateWithExtraBeforeAndAfter(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val)
|
||||
helper.accTrie.Update(common.HexToHash("0x07").Bytes(), val)
|
||||
@ -648,7 +648,7 @@ func TestGenerateWithMalformedSnapdata(t *testing.T) {
|
||||
}
|
||||
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)
|
||||
helper.accTrie.Update(common.HexToHash("0x03").Bytes(), val)
|
||||
|
||||
@ -687,7 +687,7 @@ func TestGenerateFromEmptySnap(t *testing.T) {
|
||||
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)
|
||||
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()
|
||||
t.Logf("Root: %#x\n", root) // Root: 0x6f7af6d2e1a1bf2b84a3beb3f8b64388465fbc1e274ca5d5d3fc787ca78f59e4
|
||||
@ -724,7 +724,7 @@ func TestGenerateWithIncompleteStorage(t *testing.T) {
|
||||
for i := 0; i < 8; i++ {
|
||||
accKey := fmt.Sprintf("acc-%d", i)
|
||||
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 moddedVals []string
|
||||
for ii := 0; ii < 8; ii++ {
|
||||
@ -816,11 +816,11 @@ func TestGenerateCompleteSnapshotWithDanglingStorage(t *testing.T) {
|
||||
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)
|
||||
helper.addAccount("acc-1", &Account{Balance: big.NewInt(1), Root: stRoot, CodeHash: emptyCode.Bytes()})
|
||||
helper.addAccount("acc-2", &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), 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: 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.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-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()
|
||||
|
||||
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-2", &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), 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: 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.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)
|
||||
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
@ -47,7 +48,7 @@ func randomAccount() []byte {
|
||||
Balance: big.NewInt(rand.Int63()),
|
||||
Nonce: rand.Uint64(),
|
||||
Root: root[:],
|
||||
CodeHash: emptyCode[:],
|
||||
CodeHash: types.EmptyCodeHash[:],
|
||||
}
|
||||
data, _ := rlp.EncodeToBytes(a)
|
||||
return data
|
||||
|
@ -31,8 +31,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
)
|
||||
|
||||
var emptyCodeHash = crypto.Keccak256(nil)
|
||||
|
||||
type Code []byte
|
||||
|
||||
func (c Code) String() string {
|
||||
@ -95,7 +93,7 @@ type stateObject struct {
|
||||
|
||||
// empty returns whether the account is considered empty.
|
||||
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.
|
||||
@ -104,10 +102,10 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st
|
||||
data.Balance = new(big.Int)
|
||||
}
|
||||
if data.CodeHash == nil {
|
||||
data.CodeHash = emptyCodeHash
|
||||
data.CodeHash = types.EmptyCodeHash.Bytes()
|
||||
}
|
||||
if data.Root == (common.Hash{}) {
|
||||
data.Root = emptyRoot
|
||||
data.Root = types.EmptyRootHash
|
||||
}
|
||||
return &stateObject{
|
||||
db: db,
|
||||
@ -154,7 +152,7 @@ func (s *stateObject) getTrie(db Database) (Trie, error) {
|
||||
if s.trie == nil {
|
||||
// Try fetching from prefetcher first
|
||||
// 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
|
||||
// prefetcher
|
||||
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
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
if len(s.dirtyStorage) > 0 {
|
||||
@ -454,7 +452,7 @@ func (s *stateObject) Code(db Database) []byte {
|
||||
if s.code != nil {
|
||||
return s.code
|
||||
}
|
||||
if bytes.Equal(s.CodeHash(), emptyCodeHash) {
|
||||
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
|
||||
return nil
|
||||
}
|
||||
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 {
|
||||
return len(s.code)
|
||||
}
|
||||
if bytes.Equal(s.CodeHash(), emptyCodeHash) {
|
||||
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
|
||||
return 0
|
||||
}
|
||||
size, err := db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
|
||||
|
@ -41,11 +41,6 @@ type revision struct {
|
||||
journalIndex int
|
||||
}
|
||||
|
||||
var (
|
||||
// emptyRoot is the known root hash of an empty trie.
|
||||
emptyRoot = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
)
|
||||
|
||||
type proofList [][]byte
|
||||
|
||||
func (n *proofList) Put(key []byte, value []byte) error {
|
||||
@ -589,10 +584,10 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
|
||||
Root: common.BytesToHash(acc.Root),
|
||||
}
|
||||
if len(data.CodeHash) == 0 {
|
||||
data.CodeHash = emptyCodeHash
|
||||
data.CodeHash = types.EmptyCodeHash.Bytes()
|
||||
}
|
||||
if data.Root == (common.Hash{}) {
|
||||
data.Root = emptyRoot
|
||||
data.Root = types.EmptyRootHash
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1086,11 +1081,11 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
|
||||
s.stateObjectsDestruct = make(map[common.Address]struct{})
|
||||
}
|
||||
if root == (common.Hash{}) {
|
||||
root = emptyRoot
|
||||
root = types.EmptyRootHash
|
||||
}
|
||||
origin := s.originalRoot
|
||||
if origin == (common.Hash{}) {
|
||||
origin = emptyRoot
|
||||
origin = types.EmptyRootHash
|
||||
}
|
||||
if root != origin {
|
||||
start := time.Now()
|
||||
|
@ -134,8 +134,7 @@ func checkStateConsistency(db ethdb.Database, root common.Hash) error {
|
||||
// Tests that an empty state is not scheduled for syncing.
|
||||
func TestEmptyStateSync(t *testing.T) {
|
||||
db := trie.NewDatabase(rawdb.NewMemoryDatabase())
|
||||
empty := common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421")
|
||||
sync := NewStateSync(empty, rawdb.NewMemoryDatabase(), nil, db.Scheme())
|
||||
sync := NewStateSync(types.EmptyRootHash, rawdb.NewMemoryDatabase(), nil, db.Scheme())
|
||||
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)
|
||||
}
|
||||
@ -555,7 +554,7 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||
isCode[crypto.Keccak256Hash(acc.code)] = struct{}{}
|
||||
}
|
||||
}
|
||||
isCode[common.BytesToHash(emptyCodeHash)] = struct{}{}
|
||||
isCode[types.EmptyCodeHash] = struct{}{}
|
||||
checkTrieConsistency(db, srcRoot)
|
||||
|
||||
// Create a destination state and sync with the scheduler
|
||||
|
@ -404,7 +404,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
||||
header.BaseFee = misc.CalcBaseFee(config, parent.Header())
|
||||
}
|
||||
if config.IsShanghai(header.Time) {
|
||||
header.WithdrawalsHash = &types.EmptyRootHash
|
||||
header.WithdrawalsHash = &types.EmptyWithdrawalsHash
|
||||
}
|
||||
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
|
||||
|
@ -31,11 +31,6 @@ import (
|
||||
"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
|
||||
// mix-hash) that a sufficient amount of computation has been carried
|
||||
// out on a block.
|
||||
@ -155,14 +150,14 @@ func (h *Header) SanityCheck() error {
|
||||
// that is: no transactions, no uncles and no withdrawals.
|
||||
func (h *Header) EmptyBody() bool {
|
||||
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.
|
||||
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
|
||||
@ -210,7 +205,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
|
||||
|
||||
// TODO: panic if len(txs) != len(receipts)
|
||||
if len(txs) == 0 {
|
||||
b.header.TxHash = EmptyRootHash
|
||||
b.header.TxHash = EmptyTxsHash
|
||||
} else {
|
||||
b.header.TxHash = DeriveSha(Transactions(txs), hasher)
|
||||
b.transactions = make(Transactions, len(txs))
|
||||
@ -218,7 +213,7 @@ func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*
|
||||
}
|
||||
|
||||
if len(receipts) == 0 {
|
||||
b.header.ReceiptHash = EmptyRootHash
|
||||
b.header.ReceiptHash = EmptyReceiptsHash
|
||||
} else {
|
||||
b.header.ReceiptHash = DeriveSha(Receipts(receipts), hasher)
|
||||
b.header.Bloom = CreateBloom(receipts)
|
||||
@ -250,7 +245,7 @@ func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Heade
|
||||
if withdrawals == nil {
|
||||
b.header.WithdrawalsHash = nil
|
||||
} else if len(withdrawals) == 0 {
|
||||
b.header.WithdrawalsHash = &EmptyRootHash
|
||||
b.header.WithdrawalsHash = &EmptyWithdrawalsHash
|
||||
} else {
|
||||
h := DeriveSha(Withdrawals(withdrawals), hasher)
|
||||
b.header.WithdrawalsHash = &h
|
||||
|
42
core/types/hashes.go
Normal file
42
core/types/hashes.go
Normal 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")
|
||||
)
|
@ -448,7 +448,7 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
|
||||
block, err := engine.ExecutableDataToBlock(params)
|
||||
if err != nil {
|
||||
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
|
||||
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
|
||||
// of block bodies by the engine api.
|
||||
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))
|
||||
}
|
||||
if count > 1024 {
|
||||
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested count too large: %v", count))
|
||||
}
|
||||
// limit count up until current
|
||||
current := api.eth.BlockChain().CurrentBlock().NumberU64()
|
||||
last := uint64(start) + uint64(count) - 1
|
||||
|
@ -864,8 +864,8 @@ func TestInvalidBloom(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if status.Status != engine.INVALIDBLOCKHASH {
|
||||
t.Errorf("invalid status: expected VALID got: %v", status.Status)
|
||||
if status.Status != engine.INVALID {
|
||||
t.Errorf("invalid status: expected INVALID got: %v", status.Status)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1383,37 +1383,43 @@ func TestGetBlockBodiesByRangeInvalidParams(t *testing.T) {
|
||||
node, eth, _ := setupBodies(t)
|
||||
api := NewConsensusAPI(eth)
|
||||
defer node.Close()
|
||||
|
||||
tests := []struct {
|
||||
start hexutil.Uint64
|
||||
count hexutil.Uint64
|
||||
want *engine.EngineAPIError
|
||||
}{
|
||||
// Genesis
|
||||
{
|
||||
start: 0,
|
||||
count: 1,
|
||||
want: engine.InvalidParams,
|
||||
},
|
||||
// No block requested
|
||||
{
|
||||
start: 1,
|
||||
count: 0,
|
||||
want: engine.InvalidParams,
|
||||
},
|
||||
// Genesis & no block
|
||||
{
|
||||
start: 0,
|
||||
count: 0,
|
||||
want: engine.InvalidParams,
|
||||
},
|
||||
// More than 1024 blocks
|
||||
{
|
||||
start: 1,
|
||||
count: 1025,
|
||||
want: engine.TooLargeRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
result, err := api.GetPayloadBodiesByRangeV1(test.start, test.count)
|
||||
for i, tc := range tests {
|
||||
result, err := api.GetPayloadBodiesByRangeV1(tc.start, tc.count)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +154,11 @@ type Downloader struct {
|
||||
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
|
||||
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.
|
||||
@ -231,7 +236,9 @@ func New(checkpoint uint64, stateDb ethdb.Database, mux *event.TypeMux, chain Bl
|
||||
quitCh: make(chan struct{}),
|
||||
SnapSyncer: snap.NewSyncer(stateDb, chain.TrieDB().Scheme()),
|
||||
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))
|
||||
|
||||
go dl.stateFetcher()
|
||||
@ -1614,6 +1621,7 @@ func (d *Downloader) processSnapSyncContent() error {
|
||||
if len(results) == 0 {
|
||||
// If pivot sync is done, stop
|
||||
if oldPivot == nil {
|
||||
d.reportSnapSyncProgress(true)
|
||||
return sync.Cancel()
|
||||
}
|
||||
// If sync failed, stop
|
||||
@ -1627,6 +1635,8 @@ func (d *Downloader) processSnapSyncContent() error {
|
||||
if d.chainInsertHook != nil {
|
||||
d.chainInsertHook(results)
|
||||
}
|
||||
d.reportSnapSyncProgress(false)
|
||||
|
||||
// If we haven't downloaded the pivot block yet, check pivot staleness
|
||||
// notifications from the header downloader
|
||||
d.pivotLock.RLock()
|
||||
@ -1739,7 +1749,7 @@ func (d *Downloader) commitSnapSyncData(results []*fetchResult, stateSync *state
|
||||
}
|
||||
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
|
||||
log.Debug("Inserting snap-sync blocks", "items", len(results),
|
||||
"firstnum", first.Number, "firsthash", first.Hash(),
|
||||
@ -1820,3 +1830,56 @@ func (d *Downloader) readHeaderRange(last *types.Header, count int) []*types.Hea
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ type queue struct {
|
||||
active *sync.Cond
|
||||
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.
|
||||
@ -390,11 +390,12 @@ func (q *queue) Results(block bool) []*fetchResult {
|
||||
}
|
||||
}
|
||||
// Log some info at certain times
|
||||
if time.Since(q.lastStatLog) > 60*time.Second {
|
||||
q.lastStatLog = time.Now()
|
||||
if time.Since(q.logTime) >= 60*time.Second {
|
||||
q.logTime = time.Now()
|
||||
|
||||
info := q.Stats()
|
||||
info = append(info, "throttle", throttleThreshold)
|
||||
log.Info("Downloader queue stats", info...)
|
||||
log.Debug("Downloader queue stats", info...)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ func (f *BlockFetcher) loop() {
|
||||
announce.time = task.time
|
||||
|
||||
// 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())
|
||||
|
||||
block := types.NewBlockWithHeader(header)
|
||||
|
@ -39,6 +39,7 @@ type filter struct {
|
||||
typ Type
|
||||
deadline *time.Timer // filter is inactive when deadline triggers
|
||||
hashes []common.Hash
|
||||
fullTx bool
|
||||
txs []*types.Transaction
|
||||
crit FilterCriteria
|
||||
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
|
||||
// `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 (
|
||||
pendingTxs = make(chan []*types.Transaction)
|
||||
pendingTxSub = api.events.SubscribePendingTxs(pendingTxs)
|
||||
)
|
||||
|
||||
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()
|
||||
|
||||
go func() {
|
||||
@ -412,6 +413,9 @@ func (api *FilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) {
|
||||
api.filtersMu.Lock()
|
||||
defer api.filtersMu.Unlock()
|
||||
|
||||
chainConfig := api.sys.backend.ChainConfig()
|
||||
latest := api.sys.backend.CurrentHeader()
|
||||
|
||||
if f, found := api.filters[id]; found {
|
||||
if !f.deadline.Stop() {
|
||||
// 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
|
||||
return returnHashes(hashes), nil
|
||||
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
|
||||
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:
|
||||
logs := f.logs
|
||||
f.logs = nil
|
||||
|
@ -37,6 +37,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
@ -52,11 +53,12 @@ type testBackend struct {
|
||||
}
|
||||
|
||||
func (b *testBackend) ChainConfig() *params.ChainConfig {
|
||||
panic("implement me")
|
||||
return params.TestChainConfig
|
||||
}
|
||||
|
||||
func (b *testBackend) CurrentHeader() *types.Header {
|
||||
panic("implement me")
|
||||
hdr, _ := b.HeaderByNumber(context.TODO(), rpc.LatestBlockNumber)
|
||||
return hdr
|
||||
}
|
||||
|
||||
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),
|
||||
}
|
||||
|
||||
txs []*types.Transaction
|
||||
hashes []common.Hash
|
||||
)
|
||||
|
||||
fid0 := api.NewPendingTransactionFilter()
|
||||
fid0 := api.NewPendingTransactionFilter(nil)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
backend.txFeed.Send(core.NewTxsEvent{Txs: transactions})
|
||||
@ -271,7 +273,64 @@ func TestPendingTxFilter(t *testing.T) {
|
||||
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...)
|
||||
if len(txs) >= len(transactions) {
|
||||
break
|
||||
@ -289,8 +348,8 @@ func TestPendingTxFilter(t *testing.T) {
|
||||
return
|
||||
}
|
||||
for i := range txs {
|
||||
if txs[i].Hash() != transactions[i].Hash() {
|
||||
t.Errorf("hashes[%d] invalid, want %x, got %x", i, transactions[i].Hash(), txs[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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -854,15 +913,15 @@ func TestPendingTxFilterDeadlock(t *testing.T) {
|
||||
// timeout either in 100ms or 200ms
|
||||
fids := make([]rpc.ID, 20)
|
||||
for i := 0; i < len(fids); i++ {
|
||||
fid := api.NewPendingTransactionFilter()
|
||||
fid := api.NewPendingTransactionFilter(nil)
|
||||
fids[i] = fid
|
||||
// Wait for at least one tx to arrive in filter
|
||||
for {
|
||||
txs, err := api.GetFilterChanges(fid)
|
||||
hashes, err := api.GetFilterChanges(fid)
|
||||
if err != nil {
|
||||
t.Fatalf("Filter should exist: %v\n", err)
|
||||
}
|
||||
if len(txs.([]*types.Transaction)) > 0 {
|
||||
if len(hashes.([]common.Hash)) > 0 {
|
||||
break
|
||||
}
|
||||
runtime.Gosched()
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/light"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
@ -464,7 +465,7 @@ func ServiceGetByteCodesQuery(chain *core.BlockChain, req *GetByteCodesPacket) [
|
||||
bytes uint64
|
||||
)
|
||||
for _, hash := range req.Hashes {
|
||||
if hash == emptyCode {
|
||||
if hash == types.EmptyCodeHash {
|
||||
// Peers should not request the empty code, but if they do, at
|
||||
// least sent them back a correct response without db lookups
|
||||
codes = append(codes, []byte{})
|
||||
|
@ -46,14 +46,6 @@ import (
|
||||
"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 (
|
||||
// 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.
|
||||
@ -1833,7 +1825,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) {
|
||||
res.task.pend = 0
|
||||
for i, account := range res.accounts {
|
||||
// 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)) {
|
||||
res.task.codeTasks[common.BytesToHash(account.CodeHash)] = struct{}{}
|
||||
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
|
||||
if account.Root != emptyRoot {
|
||||
if account.Root != types.EmptyRootHash {
|
||||
if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) {
|
||||
// If there was a previous large state retrieval in progress,
|
||||
// don't restart it from scratch. This happens if a sync cycle
|
||||
|
@ -1354,7 +1354,7 @@ func getCodeHash(i uint64) []byte {
|
||||
|
||||
// getCodeByHash convenience function to lookup the code from the code hash
|
||||
func getCodeByHash(hash common.Hash) []byte {
|
||||
if hash == emptyCode {
|
||||
if hash == types.EmptyCodeHash {
|
||||
return nil
|
||||
}
|
||||
for i, h := range codehashes {
|
||||
@ -1376,7 +1376,7 @@ func makeAccountTrieNoStorage(n int) (string, *trie.Trie, entrySlice) {
|
||||
value, _ := rlp.EncodeToBytes(&types.StateAccount{
|
||||
Nonce: i,
|
||||
Balance: big.NewInt(int64(i)),
|
||||
Root: emptyRoot,
|
||||
Root: types.EmptyRootHash,
|
||||
CodeHash: getCodeHash(i),
|
||||
})
|
||||
key := key32(i)
|
||||
@ -1427,7 +1427,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
|
||||
value, _ := rlp.EncodeToBytes(&types.StateAccount{
|
||||
Nonce: uint64(0),
|
||||
Balance: big.NewInt(int64(i)),
|
||||
Root: emptyRoot,
|
||||
Root: types.EmptyRootHash,
|
||||
CodeHash: getCodeHash(uint64(i)),
|
||||
})
|
||||
elem := &kv{boundaries[i].Bytes(), value}
|
||||
@ -1439,7 +1439,7 @@ func makeBoundaryAccountTrie(n int) (string, *trie.Trie, entrySlice) {
|
||||
value, _ := rlp.EncodeToBytes(&types.StateAccount{
|
||||
Nonce: i,
|
||||
Balance: big.NewInt(int64(i)),
|
||||
Root: emptyRoot,
|
||||
Root: types.EmptyRootHash,
|
||||
CodeHash: getCodeHash(i),
|
||||
})
|
||||
elem := &kv{key32(i), value}
|
||||
@ -1472,7 +1472,7 @@ func makeAccountTrieWithStorageWithUniqueStorage(accounts, slots int, code bool)
|
||||
// Create n accounts in the trie
|
||||
for i := uint64(1); i <= uint64(accounts); i++ {
|
||||
key := key32(i)
|
||||
codehash := emptyCode[:]
|
||||
codehash := types.EmptyCodeHash.Bytes()
|
||||
if code {
|
||||
codehash = getCodeHash(i)
|
||||
}
|
||||
@ -1527,7 +1527,7 @@ func makeAccountTrieWithStorage(accounts, slots int, code, boundary bool) (strin
|
||||
// Create n accounts in the trie
|
||||
for i := uint64(1); i <= uint64(accounts); i++ {
|
||||
key := key32(i)
|
||||
codehash := emptyCode[:]
|
||||
codehash := types.EmptyCodeHash.Bytes()
|
||||
if code {
|
||||
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)
|
||||
}
|
||||
accounts++
|
||||
if acc.Root != emptyRoot {
|
||||
if acc.Root != types.EmptyRootHash {
|
||||
id := trie.StorageTrieID(root, common.BytesToHash(accIt.Key), acc.Root)
|
||||
storeTrie, err := trie.NewStateTrie(id, triedb)
|
||||
if err != nil {
|
||||
|
@ -2,6 +2,7 @@ package tracers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
@ -37,7 +38,8 @@ func GetPluginTracer(pl *plugins.PluginLoader, name string) (func(*state.StateDB
|
||||
Coinbase: core.Address(vmctx.Coinbase),
|
||||
GasLimit: vmctx.GasLimit,
|
||||
BlockNumber: vmctx.BlockNumber,
|
||||
Time: vmctx.Time,
|
||||
// casting int64 zero as bigInt is foundation PluGeth only, it is being done to preserve compatability with other networks
|
||||
Time: new(big.Int).SetInt64(int64(vmctx.Time)),
|
||||
Difficulty: vmctx.Difficulty,
|
||||
BaseFee: vmctx.BaseFee,
|
||||
}))
|
||||
|
@ -131,10 +131,10 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
|
||||
if head.UncleHash != types.EmptyUncleHash && len(body.UncleHashes) == 0 {
|
||||
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")
|
||||
}
|
||||
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")
|
||||
}
|
||||
// Load uncles because they are not included in the block response.
|
||||
|
2
go.mod
2
go.mod
@ -50,7 +50,7 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.16
|
||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/openrelayxyz/plugeth-utils v0.0.23
|
||||
github.com/openrelayxyz/plugeth-utils v0.0.24
|
||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
|
||||
github.com/prometheus/tsdb v0.7.1
|
||||
github.com/rs/cors v1.7.0
|
||||
|
5
go.sum
5
go.sum
@ -292,6 +292,7 @@ github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpx
|
||||
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/holiman/big v0.0.0-20221017200358-a027dc42d04e h1:pIYdhNkDh+YENVNi3gto8n9hAmRxKxoar0iE6BLucjw=
|
||||
@ -451,8 +452,8 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/openrelayxyz/plugeth-utils v0.0.23 h1:TKNGnRPWZ3mXNUHfjr1iRjsto2r6ngNZb95dJLj2j5w=
|
||||
github.com/openrelayxyz/plugeth-utils v0.0.23/go.mod h1:zGm3/elx1rCcrYAFUQ5/He7AG/n039/3xYg0/Q8nqcQ=
|
||||
github.com/openrelayxyz/plugeth-utils v0.0.24 h1:Q2BR3SlwHovNFLbEtGrFFqgOCnL+ONyrwTC9wKKAej4=
|
||||
github.com/openrelayxyz/plugeth-utils v0.0.24/go.mod h1:W1Hwwhv04MCuNCcI6a62/kL6eWbH7OO+KvpBEyQTgIs=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
|
||||
|
@ -548,7 +548,7 @@ func (f *BlockFetcher) loop() {
|
||||
announce.time = task.time
|
||||
|
||||
// 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())
|
||||
|
||||
block := types.NewBlockWithHeader(header)
|
||||
|
@ -348,7 +348,7 @@ func handleGetReceipts(msg Decoder) (serveRequestFn, uint64, uint64, error) {
|
||||
// Retrieve the requested block's receipts, skipping if unknown to us
|
||||
results := bc.GetReceiptsByHash(hash)
|
||||
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()
|
||||
continue
|
||||
}
|
||||
|
@ -253,8 +253,8 @@ func makeHeaderChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.
|
||||
Number: big.NewInt(int64(i + 1)),
|
||||
Difficulty: big.NewInt(int64(difficulty)),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
}
|
||||
if i == 0 {
|
||||
header.ParentHash = genesis.Hash()
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
const (
|
||||
VersionMajor = 1 // Major version component of the current release
|
||||
VersionMinor = 11 // Minor version component of the current release
|
||||
VersionPatch = 1 // 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
|
||||
)
|
||||
|
||||
|
@ -100,8 +100,9 @@ func (w WrappedTracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||
func (w WrappedTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
||||
w.r.CaptureFault(pc, core.OpCode(op), gas, cost, &WrappedScopeContext{scope}, depth, err)
|
||||
}
|
||||
// passing zero as a dummy value is foundation PluGeth only, it is being done to preserve compatability with other networks
|
||||
func (w WrappedTracer) CaptureEnd(output []byte, gasUsed uint64, err error) {
|
||||
w.r.CaptureEnd(output, gasUsed, err)
|
||||
w.r.CaptureEnd(output, gasUsed, 0, err)
|
||||
}
|
||||
func (w WrappedTracer) GetResult() (json.RawMessage, error) {
|
||||
data, err := w.r.Result()
|
||||
@ -230,30 +231,30 @@ func (n *Node) Close() error {
|
||||
return n.n.Close()
|
||||
}
|
||||
|
||||
// type WrappedBlockContext struct {
|
||||
// b vm.BlockContext
|
||||
// }
|
||||
//
|
||||
// //type WrappedBlockContext vm.BlockContext
|
||||
//
|
||||
// func NewWrappedBlockContext(c vm.BlockContext) *WrappedBlockContext {
|
||||
// return &WrappedBlockContext{c}
|
||||
// }
|
||||
// func (w *WrappedBlockContext) Coinbase() core.Address {
|
||||
// return core.Address(w.b.Coinbase)
|
||||
// }
|
||||
// func (w *WrappedBlockContext) GasLimit() uint64 {
|
||||
// return w.b.GasLimit
|
||||
// }
|
||||
// func (w *WrappedBlockContext) BlockNumber() *big.Int {
|
||||
// return w.b.BlockNumber
|
||||
// }
|
||||
// func (w *WrappedBlockContext) Time() *big.Int {
|
||||
// return w.b.Time
|
||||
// }
|
||||
// func (w *WrappedBlockContext) Difficulty() *big.Int {
|
||||
// return w.b.Difficulty
|
||||
// }
|
||||
// func (w *WrappedBlockContext) BaseFee() *big.Int {
|
||||
// return w.b.BaseFee
|
||||
// }
|
||||
type WrappedBlockContext struct {
|
||||
b vm.BlockContext
|
||||
}
|
||||
|
||||
// type WrappedBlockContext vm.BlockContext
|
||||
|
||||
func NewWrappedBlockContext(c vm.BlockContext) *WrappedBlockContext {
|
||||
return &WrappedBlockContext{c}
|
||||
}
|
||||
func (w *WrappedBlockContext) Coinbase() core.Address {
|
||||
return core.Address(w.b.Coinbase)
|
||||
}
|
||||
func (w *WrappedBlockContext) GasLimit() uint64 {
|
||||
return w.b.GasLimit
|
||||
}
|
||||
func (w *WrappedBlockContext) BlockNumber() *big.Int {
|
||||
return w.b.BlockNumber
|
||||
}
|
||||
func (w *WrappedBlockContext) Time() *big.Int {
|
||||
return new(big.Int).SetInt64(int64(w.b.Time))
|
||||
}
|
||||
func (w *WrappedBlockContext) Difficulty() *big.Int {
|
||||
return w.b.Difficulty
|
||||
}
|
||||
func (w *WrappedBlockContext) BaseFee() *big.Int {
|
||||
return w.b.BaseFee
|
||||
}
|
||||
|
@ -345,7 +345,10 @@ func (c *Client) CallContext(ctx context.Context, result interface{}, method str
|
||||
case len(resp.Result) == 0:
|
||||
return ErrNoResult
|
||||
default:
|
||||
return json.Unmarshal(resp.Result, &result)
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(resp.Result, result)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
func TestClientErrorData(t *testing.T) {
|
||||
server := newTestServer()
|
||||
|
@ -45,7 +45,7 @@ func TestServerRegisterName(t *testing.T) {
|
||||
t.Fatalf("Expected service calc to be registered")
|
||||
}
|
||||
|
||||
wantCallbacks := 12
|
||||
wantCallbacks := 13
|
||||
if len(svc.callbacks) != wantCallbacks {
|
||||
t.Errorf("Expected %d callbacks for service 'service', got %d", wantCallbacks, len(svc.callbacks))
|
||||
}
|
||||
|
@ -78,6 +78,10 @@ func (o *MarshalErrObj) MarshalText() ([]byte, error) {
|
||||
|
||||
func (s *testService) NoArgsRets() {}
|
||||
|
||||
func (s *testService) Null() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *testService) Echo(str string, i int, args *echoArgs) echoResult {
|
||||
return echoResult{str, i, args}
|
||||
}
|
||||
|
@ -808,7 +808,7 @@ func (db *Database) Update(nodes *MergedNodeSet) error {
|
||||
if err := rlp.DecodeBytes(n.blob, &account); err != nil {
|
||||
return err
|
||||
}
|
||||
if account.Root != emptyRoot {
|
||||
if account.Root != types.EmptyRootHash {
|
||||
db.reference(account.Root, n.parent)
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"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
|
||||
@ -160,7 +161,7 @@ func (e seekError) Error() string {
|
||||
}
|
||||
|
||||
func newNodeIterator(trie *Trie, start []byte) NodeIterator {
|
||||
if trie.Hash() == emptyRoot {
|
||||
if trie.Hash() == types.EmptyRootHash {
|
||||
return &nodeIterator{
|
||||
trie: trie,
|
||||
err: errIteratorEnd,
|
||||
@ -302,7 +303,7 @@ func (it *nodeIterator) seek(prefix []byte) error {
|
||||
func (it *nodeIterator) init() (*nodeIteratorState, error) {
|
||||
root := it.trie.Hash()
|
||||
state := &nodeIteratorState{node: it.trie.root, index: -1}
|
||||
if root != emptyRoot {
|
||||
if root != types.EmptyRootHash {
|
||||
state.hash = root
|
||||
}
|
||||
return state, state.resolve(it, nil)
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
@ -407,7 +408,7 @@ func (st *StackTrie) hashRec(hasher *hasher, path []byte) {
|
||||
return
|
||||
|
||||
case emptyNode:
|
||||
st.val = emptyRoot.Bytes()
|
||||
st.val = types.EmptyRootHash.Bytes()
|
||||
st.key = st.key[:0]
|
||||
st.nodeType = hashedNode
|
||||
return
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/prque"
|
||||
"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/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.
|
||||
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
|
||||
if root == emptyRoot {
|
||||
if root == types.EmptyRootHash {
|
||||
return
|
||||
}
|
||||
if s.membatch.hasNode(path) {
|
||||
@ -217,7 +218,7 @@ func (s *Sync) AddSubTrie(root common.Hash, path []byte, parent common.Hash, par
|
||||
// as is.
|
||||
func (s *Sync) AddCodeEntry(hash common.Hash, path []byte, parent common.Hash, parentPath []byte) {
|
||||
// Short circuit if the entry is empty or already known
|
||||
if hash == emptyState {
|
||||
if hash == types.EmptyCodeHash {
|
||||
return
|
||||
}
|
||||
if s.membatch.hasCode(hash) {
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"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/ethdb/memorydb"
|
||||
)
|
||||
@ -104,7 +105,7 @@ func TestEmptySync(t *testing.T) {
|
||||
dbA := NewDatabase(rawdb.NewMemoryDatabase())
|
||||
dbB := NewDatabase(rawdb.NewMemoryDatabase())
|
||||
emptyA, _ := New(TrieID(common.Hash{}), dbA)
|
||||
emptyB, _ := New(TrieID(emptyRoot), dbB)
|
||||
emptyB, _ := New(TrieID(types.EmptyRootHash), dbB)
|
||||
|
||||
for i, trie := range []*Trie{emptyA, emptyB} {
|
||||
sync := NewSync(trie.Hash(), memorydb.New(), nil, []*Database{dbA, dbB}[i].Scheme())
|
||||
|
16
trie/trie.go
16
trie/trie.go
@ -23,18 +23,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
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
|
||||
// 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,
|
||||
@ -91,7 +83,7 @@ func New(id *ID, db NodeReader) (*Trie, error) {
|
||||
reader: reader,
|
||||
//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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -576,7 +568,7 @@ func (t *Trie) Commit(collectLeaf bool) (common.Hash, *NodeSet) {
|
||||
// Wrap tracked deletions as the return
|
||||
set := NewNodeSet(t.owner)
|
||||
t.tracer.markDeletions(set)
|
||||
return emptyRoot, set
|
||||
return types.EmptyRootHash, set
|
||||
}
|
||||
// Derive the hash for all dirty nodes first. We hold the assumption
|
||||
// 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
|
||||
func (t *Trie) hashRoot() (node, node, error) {
|
||||
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
|
||||
h := newHasher(t.unhashed >= 100)
|
||||
|
@ -47,7 +47,7 @@ func init() {
|
||||
func TestEmptyTrie(t *testing.T) {
|
||||
trie := NewEmpty(NewDatabase(rawdb.NewMemoryDatabase()))
|
||||
res := trie.Hash()
|
||||
exp := emptyRoot
|
||||
exp := types.EmptyRootHash
|
||||
if res != exp {
|
||||
t.Errorf("expected %x got %x", exp, res)
|
||||
}
|
||||
@ -431,7 +431,7 @@ func runRandTest(rt randTest) bool {
|
||||
}
|
||||
case opProve:
|
||||
hash := tr.Hash()
|
||||
if hash == emptyRoot {
|
||||
if hash == types.EmptyRootHash {
|
||||
continue
|
||||
}
|
||||
proofDb := rawdb.NewMemoryDatabase()
|
||||
@ -718,7 +718,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
|
||||
for i := 0; i < len(accounts); i++ {
|
||||
var (
|
||||
nonce = uint64(random.Int63())
|
||||
root = emptyRoot
|
||||
root = types.EmptyRootHash
|
||||
code = crypto.Keccak256(nil)
|
||||
)
|
||||
// The big.Rand function is not deterministic with regards to 64 vs 32 bit systems,
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// Tests if the trie diffs are tracked correctly.
|
||||
@ -286,7 +287,7 @@ func TestDeleteAll(t *testing.T) {
|
||||
trie.Delete([]byte(val.k))
|
||||
}
|
||||
root, set = trie.Commit(false)
|
||||
if root != emptyRoot {
|
||||
if root != types.EmptyRootHash {
|
||||
t.Fatalf("Invalid trie root %v", root)
|
||||
}
|
||||
for path, blob := range set.deletes {
|
||||
|
Loading…
Reference in New Issue
Block a user