mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-01 17:43:45 +00:00
Merge branch 'ethereum:master' into portal
This commit is contained in:
commit
915ab84d3b
13 changed files with 116 additions and 42 deletions
|
|
@ -5,22 +5,22 @@
|
|||
# https://github.com/ethereum/execution-spec-tests/releases/download/v1.0.6/
|
||||
485af7b66cf41eb3a8c1bd46632913b8eb95995df867cf665617bbc9b4beedd1 fixtures_develop.tar.gz
|
||||
|
||||
# version:golang 1.21.3
|
||||
# version:golang 1.21.4
|
||||
# https://go.dev/dl/
|
||||
186f2b6f8c8b704e696821b09ab2041a5c1ee13dcbc3156a13adcf75931ee488 go1.21.3.src.tar.gz
|
||||
27014fc69e301d7588a169ca239b3cc609f0aa1abf38528bf0d20d3b259211eb go1.21.3.darwin-amd64.tar.gz
|
||||
65302a7a9f7a4834932b3a7a14cb8be51beddda757b567a2f9e0cbd0d7b5a6ab go1.21.3.darwin-arm64.tar.gz
|
||||
8e0cd2f66cf1bde9d07b4aee01e3d7c3cfdd14e20650488e1683da4b8492594a go1.21.3.freebsd-386.tar.gz
|
||||
6e74f65f586e93d1f3947894766f69e9b2ebda488592a09df61f36f06bfe58a8 go1.21.3.freebsd-amd64.tar.gz
|
||||
fb209fd070db500a84291c5a95251cceeb1723e8f6142de9baca5af70a927c0e go1.21.3.linux-386.tar.gz
|
||||
1241381b2843fae5a9707eec1f8fb2ef94d827990582c7c7c32f5bdfbfd420c8 go1.21.3.linux-amd64.tar.gz
|
||||
fc90fa48ae97ba6368eecb914343590bbb61b388089510d0c56c2dde52987ef3 go1.21.3.linux-arm64.tar.gz
|
||||
a1ddcaaf0821a12a800884c14cb4268ce1c1f5a0301e9060646f1e15e611c6c7 go1.21.3.linux-armv6l.tar.gz
|
||||
3b0e10a3704f164a6e85e0377728ec5fd21524fabe4c925610e34076586d5826 go1.21.3.linux-ppc64le.tar.gz
|
||||
4c78e2e6f4c684a3d5a9bdc97202729053f44eb7be188206f0627ef3e18716b6 go1.21.3.linux-s390x.tar.gz
|
||||
e36737f4f2fadb4d2f919ec4ce517133a56e06064cca6e82fc883bb000c4d56c go1.21.3.windows-386.zip
|
||||
27c8daf157493f288d42a6f38debc6a2cb391f6543139eba9152fceca0be2a10 go1.21.3.windows-amd64.zip
|
||||
bfb7a5c56f9ded07d8ae0e0b3702ac07b65e68fa8f33da24ed6df4ce01fe2c5c go1.21.3.windows-arm64.zip
|
||||
47b26a83d2b65a3c1c1bcace273b69bee49a7a7b5168a7604ded3d26a37bd787 go1.21.4.src.tar.gz
|
||||
cd3bdcc802b759b70e8418bc7afbc4a65ca73a3fe576060af9fc8a2a5e71c3b8 go1.21.4.darwin-amd64.tar.gz
|
||||
8b7caf2ac60bdff457dba7d4ff2a01def889592b834453431ae3caecf884f6a5 go1.21.4.darwin-arm64.tar.gz
|
||||
f1e685d086eb36f4be5b8b953b52baf7752bc6235400d84bb7d87e500b65f03e go1.21.4.freebsd-386.tar.gz
|
||||
59f9b32187efb98d344a3818a631d3815ebb5c7bbefc367bab6515caaca544e9 go1.21.4.freebsd-amd64.tar.gz
|
||||
64d3e5d295806e137c9e39d1e1f10b00a30fcd5c2f230d72b3298f579bb3c89a go1.21.4.linux-386.tar.gz
|
||||
73cac0215254d0c7d1241fa40837851f3b9a8a742d0b54714cbdfb3feaf8f0af go1.21.4.linux-amd64.tar.gz
|
||||
ce1983a7289856c3a918e1fd26d41e072cc39f928adfb11ba1896440849b95da go1.21.4.linux-arm64.tar.gz
|
||||
6c62e89113750cc77c498194d13a03fadfda22bd2c7d44e8a826fd354db60252 go1.21.4.linux-armv6l.tar.gz
|
||||
2c63b36d2adcfb22013102a2ee730f058ec2f93b9f27479793c80b2e3641783f go1.21.4.linux-ppc64le.tar.gz
|
||||
7a75ba4afc7a96058ca65903d994cd862381825d7dca12b2183f087c757c26c0 go1.21.4.linux-s390x.tar.gz
|
||||
870a0e462b94671dc2d6cac707e9e19f7524fdc3c90711e6cd4450c3713a8ce0 go1.21.4.windows-386.zip
|
||||
79e5428e068c912d9cfa6cd115c13549856ec689c1332eac17f5d6122e19d595 go1.21.4.windows-amd64.zip
|
||||
58bc7c6f4d4c72da2df4d2650c8222fe03c9978070eb3c66be8bbaa2a4757ac1 go1.21.4.windows-arm64.zip
|
||||
|
||||
# version:golangci 1.51.1
|
||||
# https://github.com/golangci/golangci-lint/releases/
|
||||
|
|
|
|||
|
|
@ -108,13 +108,14 @@ func runStateTest(fname string, cfg vm.Config, jsonOut, dump bool) error {
|
|||
fmt.Fprintf(os.Stderr, "{\"stateRoot\": \"%#x\"}\n", root)
|
||||
}
|
||||
}
|
||||
// Dump any state to aid debugging
|
||||
if dump {
|
||||
dump := state.RawDump(nil)
|
||||
result.State = &dump
|
||||
}
|
||||
if err != nil {
|
||||
// Test failed, mark as so and dump any state to aid debugging
|
||||
// Test failed, mark as so
|
||||
result.Pass, result.Error = false, err.Error()
|
||||
if dump {
|
||||
dump := state.RawDump(nil)
|
||||
result.State = &dump
|
||||
}
|
||||
}
|
||||
})
|
||||
results = append(results, *result)
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ a data corruption.`,
|
|||
utils.CacheFlag,
|
||||
utils.CacheDatabaseFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `This command performs a database compaction.
|
||||
Description: `This command performs a database compaction.
|
||||
WARNING: This operation may take a very long time to finish, and may cause database
|
||||
corruption if it is aborted during execution'!`,
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ corruption if it is aborted during execution'!`,
|
|||
Flags: flags.Merge([]cli.Flag{
|
||||
utils.SyncModeFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `This command deletes the specified database key from the database.
|
||||
Description: `This command deletes the specified database key from the database.
|
||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||
}
|
||||
dbPutCmd = &cli.Command{
|
||||
|
|
@ -141,7 +141,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||
Flags: flags.Merge([]cli.Flag{
|
||||
utils.SyncModeFlag,
|
||||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `This command sets a given database key to the given value.
|
||||
Description: `This command sets a given database key to the given value.
|
||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||
}
|
||||
dbGetSlotsCmd = &cli.Command{
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ In other words, this command does the snapshot to trie conversion.
|
|||
Action: checkDanglingStorage,
|
||||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `
|
||||
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
||||
data, and verifies that all snapshot storage data has a corresponding account.
|
||||
geth snapshot check-dangling-storage <state-root> traverses the snap storage
|
||||
data, and verifies that all snapshot storage data has a corresponding account.
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
|
@ -96,7 +96,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
|
|||
Flags: flags.Merge(utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `
|
||||
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
|
||||
information about the specified address.
|
||||
information about the specified address.
|
||||
`,
|
||||
},
|
||||
{
|
||||
|
|
@ -125,7 +125,7 @@ geth snapshot traverse-rawstate <state-root>
|
|||
will traverse the whole state from the given root and will abort if any referenced
|
||||
trie node or contract code is missing. This command can be used for state integrity
|
||||
verification. The default checking target is the HEAD state. It's basically identical
|
||||
to traverse-state, but the check granularity is smaller.
|
||||
to traverse-state, but the check granularity is smaller.
|
||||
|
||||
It's also usable without snapshot enabled.
|
||||
`,
|
||||
|
|
@ -143,7 +143,7 @@ It's also usable without snapshot enabled.
|
|||
}, utils.NetworkFlags, utils.DatabaseFlags),
|
||||
Description: `
|
||||
This command is semantically equivalent to 'geth dump', but uses the snapshots
|
||||
as the backend data source, making this command a lot faster.
|
||||
as the backend data source, making this command a lot faster.
|
||||
|
||||
The argument is interpreted as block number or hash. If none is provided, the latest
|
||||
block is used.
|
||||
|
|
|
|||
|
|
@ -2045,12 +2045,11 @@ func SplitTagsFlag(tagsFlag string) map[string]string {
|
|||
return tagsMap
|
||||
}
|
||||
|
||||
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
|
||||
// MakeChainDatabase opens a database using the flags passed to the client and will hard crash if it fails.
|
||||
func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
|
||||
var (
|
||||
cache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
|
||||
handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
|
||||
|
||||
err error
|
||||
chainDb ethdb.Database
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package rawdb
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
|
|
@ -126,6 +127,8 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
|
|||
switch freezerName {
|
||||
case chainFreezerName:
|
||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||
case stateFreezerName:
|
||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||
default:
|
||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,19 +182,27 @@ func (batch *freezerTableBatch) maybeCommit() error {
|
|||
|
||||
// commit writes the batched items to the backing freezerTable.
|
||||
func (batch *freezerTableBatch) commit() error {
|
||||
// Write data.
|
||||
// Write data. The head file is fsync'd after write to ensure the
|
||||
// data is truly transferred to disk.
|
||||
_, err := batch.t.head.Write(batch.dataBuffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.t.head.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
dataSize := int64(len(batch.dataBuffer))
|
||||
batch.dataBuffer = batch.dataBuffer[:0]
|
||||
|
||||
// Write indices.
|
||||
// Write indices. The index file is fsync'd after write to ensure the
|
||||
// data indexes are truly transferred to disk.
|
||||
_, err = batch.t.index.Write(batch.indexBuffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := batch.t.index.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
indexSize := int64(len(batch.indexBuffer))
|
||||
batch.indexBuffer = batch.indexBuffer[:0]
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,9 @@ func (t *freezerTable) repair() error {
|
|||
if t.readonly {
|
||||
return fmt.Errorf("index file(path: %s, name: %s) size is not a multiple of %d", t.path, t.name, indexEntrySize)
|
||||
}
|
||||
truncateFreezerFile(t.index, stat.Size()-overflow) // New file can't trigger this path
|
||||
if err := truncateFreezerFile(t.index, stat.Size()-overflow); err != nil {
|
||||
return err
|
||||
} // New file can't trigger this path
|
||||
}
|
||||
// Retrieve the file sizes and prepare for truncation
|
||||
if stat, err = t.index.Stat(); err != nil {
|
||||
|
|
@ -260,8 +262,8 @@ func (t *freezerTable) repair() error {
|
|||
// Print an error log if the index is corrupted due to an incorrect
|
||||
// last index item. While it is theoretically possible to have a zero offset
|
||||
// by storing all zero-size items, it is highly unlikely to occur in practice.
|
||||
if lastIndex.offset == 0 && offsetsSize%indexEntrySize > 1 {
|
||||
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "items", offsetsSize%indexEntrySize-1)
|
||||
if lastIndex.offset == 0 && offsetsSize/indexEntrySize > 1 {
|
||||
log.Error("Corrupted index file detected", "lastOffset", lastIndex.offset, "indexes", offsetsSize/indexEntrySize)
|
||||
}
|
||||
if t.readonly {
|
||||
t.head, err = t.openFile(lastIndex.filenum, openFreezerFileForReadOnly)
|
||||
|
|
@ -416,6 +418,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
|||
if err := truncateFreezerFile(t.index, int64(length+1)*indexEntrySize); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.index.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Calculate the new expected size of the data file and truncate it
|
||||
var expected indexEntry
|
||||
if length == 0 {
|
||||
|
|
@ -438,6 +443,7 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
|||
// Release any files _after the current head -- both the previous head
|
||||
// and any files which may have been opened for reading
|
||||
t.releaseFilesAfter(expected.filenum, true)
|
||||
|
||||
// Set back the historic head
|
||||
t.head = newHead
|
||||
t.headId = expected.filenum
|
||||
|
|
@ -445,6 +451,9 @@ func (t *freezerTable) truncateHead(items uint64) error {
|
|||
if err := truncateFreezerFile(t.head, int64(expected.offset)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.head.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
// All data files truncated, set internal counters and return
|
||||
t.headBytes = int64(expected.offset)
|
||||
t.items.Store(items)
|
||||
|
|
@ -589,10 +598,12 @@ func (t *freezerTable) Close() error {
|
|||
// error on Windows.
|
||||
doClose(t.index, true, true)
|
||||
doClose(t.meta, true, true)
|
||||
|
||||
// The preopened non-head data-files are all opened in readonly.
|
||||
// The head is opened in rw-mode, so we sync it here - but since it's also
|
||||
// part of t.files, it will be closed in the loop below.
|
||||
doClose(t.head, true, false) // sync but do not close
|
||||
|
||||
for _, f := range t.files {
|
||||
doClose(f, false, true) // close but do not sync
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,11 +73,7 @@ func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) e
|
|||
return err
|
||||
}
|
||||
f = nil
|
||||
|
||||
if err := os.Rename(fname, destPath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return os.Rename(fname, destPath)
|
||||
}
|
||||
|
||||
// openFreezerFileForAppend opens a freezer table file and seeks to the end
|
||||
|
|
|
|||
|
|
@ -37,8 +37,12 @@ var (
|
|||
errInvalidTopic = errors.New("invalid topic(s)")
|
||||
errFilterNotFound = errors.New("filter not found")
|
||||
errInvalidBlockRange = errors.New("invalid block range params")
|
||||
errExceedMaxTopics = errors.New("exceed max topics")
|
||||
)
|
||||
|
||||
// The maximum number of topic criteria allowed, vm.LOG4 - vm.LOG0
|
||||
const maxTopics = 4
|
||||
|
||||
// filter is a helper struct that holds meta information over the filter type
|
||||
// and associated subscription in the event system.
|
||||
type filter struct {
|
||||
|
|
@ -334,6 +338,9 @@ func (api *FilterAPI) NewFilter(crit FilterCriteria) (rpc.ID, error) {
|
|||
|
||||
// GetLogs returns logs matching the given argument that are stored within the state.
|
||||
func (api *FilterAPI) GetLogs(ctx context.Context, crit FilterCriteria) ([]*types.Log, error) {
|
||||
if len(crit.Topics) > maxTopics {
|
||||
return nil, errExceedMaxTopics
|
||||
}
|
||||
var filter *Filter
|
||||
if crit.BlockHash != nil {
|
||||
// Block filter requested, construct a single-shot filter
|
||||
|
|
|
|||
|
|
@ -299,6 +299,9 @@ func (es *EventSystem) subscribe(sub *subscription) *Subscription {
|
|||
// given criteria to the given logs channel. Default value for the from and to
|
||||
// block is "latest". If the fromBlock > toBlock an error is returned.
|
||||
func (es *EventSystem) SubscribeLogs(crit ethereum.FilterQuery, logs chan []*types.Log) (*Subscription, error) {
|
||||
if len(crit.Topics) > maxTopics {
|
||||
return nil, errExceedMaxTopics
|
||||
}
|
||||
var from, to rpc.BlockNumber
|
||||
if crit.FromBlock == nil {
|
||||
from = rpc.LatestBlockNumber
|
||||
|
|
|
|||
|
|
@ -386,6 +386,8 @@ func TestLogFilterCreation(t *testing.T) {
|
|||
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)}, false},
|
||||
// from block "higher" than to block
|
||||
{FilterCriteria{FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())}, false},
|
||||
// topics more then 4
|
||||
{FilterCriteria{Topics: [][]common.Hash{{}, {}, {}, {}, {}}}, false},
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -420,6 +422,7 @@ func TestInvalidLogFilterCreation(t *testing.T) {
|
|||
0: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||
1: {FromBlock: big.NewInt(rpc.PendingBlockNumber.Int64()), ToBlock: big.NewInt(100)},
|
||||
2: {FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(100)},
|
||||
3: {Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
|
|
@ -445,6 +448,7 @@ func TestInvalidGetLogsRequest(t *testing.T) {
|
|||
0: {BlockHash: &blockHash, FromBlock: big.NewInt(100)},
|
||||
1: {BlockHash: &blockHash, ToBlock: big.NewInt(500)},
|
||||
2: {BlockHash: &blockHash, FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||
3: {BlockHash: &blockHash, Topics: [][]common.Hash{{}, {}, {}, {}, {}}},
|
||||
}
|
||||
|
||||
for i, test := range testCases {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ var (
|
|||
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
|
||||
testContract = common.HexToAddress("0xbeef")
|
||||
testEmpty = common.HexToAddress("0xeeee")
|
||||
testSlot = common.HexToHash("0xdeadbeef")
|
||||
testValue = crypto.Keccak256Hash(testSlot[:])
|
||||
testBalance = big.NewInt(2e15)
|
||||
|
|
@ -80,8 +81,11 @@ func newTestBackend(t *testing.T) (*node.Node, []*types.Block) {
|
|||
func generateTestChain() (*core.Genesis, []*types.Block) {
|
||||
genesis := &core.Genesis{
|
||||
Config: params.AllEthashProtocolChanges,
|
||||
Alloc: core.GenesisAlloc{testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
|
||||
testContract: {Nonce: 1, Code: []byte{0x13, 0x37}}},
|
||||
Alloc: core.GenesisAlloc{
|
||||
testAddr: {Balance: testBalance, Storage: map[common.Hash]common.Hash{testSlot: testValue}},
|
||||
testContract: {Nonce: 1, Code: []byte{0x13, 0x37}},
|
||||
testEmpty: {Balance: big.NewInt(1)},
|
||||
},
|
||||
ExtraData: []byte("test genesis"),
|
||||
Timestamp: 9000,
|
||||
}
|
||||
|
|
@ -110,6 +114,12 @@ func TestGethClient(t *testing.T) {
|
|||
}, {
|
||||
"TestGetProof2",
|
||||
func(t *testing.T) { testGetProof(t, client, testContract) },
|
||||
}, {
|
||||
"TestGetProofEmpty",
|
||||
func(t *testing.T) { testGetProof(t, client, testEmpty) },
|
||||
}, {
|
||||
"TestGetProofNonExistent",
|
||||
func(t *testing.T) { testGetProofNonExistent(t, client) },
|
||||
}, {
|
||||
"TestGetProofCanonicalizeKeys",
|
||||
func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) },
|
||||
|
|
@ -274,6 +284,38 @@ func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) {
|
|||
}
|
||||
}
|
||||
|
||||
func testGetProofNonExistent(t *testing.T, client *rpc.Client) {
|
||||
addr := common.HexToAddress("0x0001")
|
||||
ec := New(client)
|
||||
result, err := ec.GetProof(context.Background(), addr, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Address != addr {
|
||||
t.Fatalf("unexpected address, have: %v want: %v", result.Address, addr)
|
||||
}
|
||||
// test nonce
|
||||
if result.Nonce != 0 {
|
||||
t.Fatalf("invalid nonce, want: %v got: %v", 0, result.Nonce)
|
||||
}
|
||||
// test balance
|
||||
if result.Balance.Cmp(big.NewInt(0)) != 0 {
|
||||
t.Fatalf("invalid balance, want: %v got: %v", 0, result.Balance)
|
||||
}
|
||||
// test storage
|
||||
if have := len(result.StorageProof); have != 0 {
|
||||
t.Fatalf("invalid storage proof, want 0 proof, got %v proof(s)", have)
|
||||
}
|
||||
// test codeHash
|
||||
if have, want := result.CodeHash, (common.Hash{}); have != want {
|
||||
t.Fatalf("codehash wrong, have %v want %v ", have, want)
|
||||
}
|
||||
// test codeHash
|
||||
if have, want := result.StorageHash, (common.Hash{}); have != want {
|
||||
t.Fatalf("storagehash wrong, have %v want %v ", have, want)
|
||||
}
|
||||
}
|
||||
|
||||
func testGCStats(t *testing.T, client *rpc.Client) {
|
||||
ec := New(client)
|
||||
_, err := ec.GCStats(context.Background())
|
||||
|
|
|
|||
Loading…
Reference in a new issue