Merge branch 'ethereum:master' into master

This commit is contained in:
hmoens 2022-09-01 16:57:20 +02:00 committed by GitHub
commit d6a2c62fb6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
338 changed files with 4608 additions and 3891 deletions

View file

@ -28,6 +28,7 @@ linters:
- durationcheck - durationcheck
- exportloopref - exportloopref
- gosec - gosec
- whitespace
# - structcheck # lots of false positives # - structcheck # lots of false positives
# - errcheck #lot of false positives # - errcheck #lot of false positives

View file

@ -14,7 +14,7 @@ COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download RUN cd /go-ethereum && go mod download
ADD . /go-ethereum ADD . /go-ethereum
RUN cd /go-ethereum && go run build/ci.go install ./cmd/geth RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
# Pull Geth into a second stage deploy alpine container # Pull Geth into a second stage deploy alpine container
FROM alpine:latest FROM alpine:latest

View file

@ -14,7 +14,7 @@ COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download RUN cd /go-ethereum && go mod download
ADD . /go-ethereum ADD . /go-ethereum
RUN cd /go-ethereum && go run build/ci.go install RUN cd /go-ethereum && go run build/ci.go install -static
# Pull all binaries into a second stage deploy alpine container # Pull all binaries into a second stage deploy alpine container
FROM alpine:latest FROM alpine:latest

View file

@ -1,6 +1,6 @@
## Go Ethereum ## Go Ethereum
Official Golang implementation of the Ethereum protocol. Official Golang execution layer implementation of the Ethereum protocol.
[![API Reference]( [![API Reference](
https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667 https://camo.githubusercontent.com/915b7be44ada53c290eb157634330494ebe3e30a/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f676f6c616e672f6764646f3f7374617475732e737667

View file

@ -95,7 +95,7 @@ func (abi ABI) getArguments(name string, data []byte) (Arguments, error) {
args = event.Inputs args = event.Inputs
} }
if args == nil { if args == nil {
return nil, errors.New("abi: could not locate named method or event") return nil, fmt.Errorf("abi: could not locate named method or event: %s", name)
} }
return args, nil return args, nil
} }

View file

@ -68,7 +68,8 @@ type SimulatedBackend struct {
pendingState *state.StateDB // Currently pending state that will be the active on request pendingState *state.StateDB // Currently pending state that will be the active on request
pendingReceipts types.Receipts // Currently receipts for the pending block pendingReceipts types.Receipts // Currently receipts for the pending block
events *filters.EventSystem // Event system for filtering log events live events *filters.EventSystem // for filtering log events live
filterSystem *filters.FilterSystem // for filtering database logs
config *params.ChainConfig config *params.ChainConfig
} }
@ -79,14 +80,18 @@ type SimulatedBackend struct {
func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend {
genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc} genesis := core.Genesis{Config: params.AllEthashProtocolChanges, GasLimit: gasLimit, Alloc: alloc}
genesis.MustCommit(database) genesis.MustCommit(database)
blockchain, _ := core.NewBlockChain(database, nil, genesis.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := core.NewBlockChain(database, nil, &genesis, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
backend := &SimulatedBackend{ backend := &SimulatedBackend{
database: database, database: database,
blockchain: blockchain, blockchain: blockchain,
config: genesis.Config, config: genesis.Config,
} }
backend.events = filters.NewEventSystem(&filterBackend{database, blockchain, backend}, false)
filterBackend := &filterBackend{database, blockchain, backend}
backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{})
backend.events = filters.NewEventSystem(backend.filterSystem, false)
backend.rollback(blockchain.CurrentBlock()) backend.rollback(blockchain.CurrentBlock())
return backend return backend
} }
@ -609,7 +614,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// User specified the legacy gas field, convert to 1559 gas typing // User specified the legacy gas field, convert to 1559 gas typing
call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice call.GasFeeCap, call.GasTipCap = call.GasPrice, call.GasPrice
} else { } else {
// User specified 1559 gas feilds (or none), use those // User specified 1559 gas fields (or none), use those
if call.GasFeeCap == nil { if call.GasFeeCap == nil {
call.GasFeeCap = new(big.Int) call.GasFeeCap = new(big.Int)
} }
@ -689,7 +694,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
var filter *filters.Filter var filter *filters.Filter
if query.BlockHash != nil { if query.BlockHash != nil {
// Block filter requested, construct a single-shot filter // Block filter requested, construct a single-shot filter
filter = filters.NewBlockFilter(&filterBackend{b.database, b.blockchain, b}, *query.BlockHash, query.Addresses, query.Topics) filter = b.filterSystem.NewBlockFilter(*query.BlockHash, query.Addresses, query.Topics)
} else { } else {
// Initialize unset filter boundaries to run from genesis to chain head // Initialize unset filter boundaries to run from genesis to chain head
from := int64(0) from := int64(0)
@ -701,7 +706,7 @@ func (b *SimulatedBackend) FilterLogs(ctx context.Context, query ethereum.Filter
to = query.ToBlock.Int64() to = query.ToBlock.Int64()
} }
// Construct the range filter // Construct the range filter
filter = filters.NewRangeFilter(&filterBackend{b.database, b.blockchain, b}, from, to, query.Addresses, query.Topics) filter = b.filterSystem.NewRangeFilter(from, to, query.Addresses, query.Topics)
} }
// Run the filter and return all the logs // Run the filter and return all the logs
logs, err := filter.Logs(ctx) logs, err := filter.Logs(ctx)
@ -828,6 +833,7 @@ type filterBackend struct {
} }
func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db } func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") } func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) { func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) {
@ -853,19 +859,8 @@ func (fb *filterBackend) GetReceipts(ctx context.Context, hash common.Hash) (typ
return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil return rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config()), nil
} }
func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { func (fb *filterBackend) GetLogs(ctx context.Context, hash common.Hash, number uint64) ([][]*types.Log, error) {
number := rawdb.ReadHeaderNumber(fb.db, hash) logs := rawdb.ReadLogs(fb.db, hash, number, fb.bc.Config())
if number == nil {
return nil, nil
}
receipts := rawdb.ReadReceipts(fb.db, hash, *number, fb.bc.Config())
if receipts == nil {
return nil, nil
}
logs := make([][]*types.Log, len(receipts))
for i, receipt := range receipts {
logs[i] = receipt.Logs
}
return logs, nil return logs, nil
} }

View file

@ -32,6 +32,8 @@ import (
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
) )
const basefeeWiggleMultiplier = 2
// SignerFn is a signer function callback when a contract requires a method to // SignerFn is a signer function callback when a contract requires a method to
// sign the transaction before submission. // sign the transaction before submission.
type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error) type SignerFn func(common.Address, *types.Transaction) (*types.Transaction, error)
@ -254,7 +256,7 @@ func (c *BoundContract) createDynamicTx(opts *TransactOpts, contract *common.Add
if gasFeeCap == nil { if gasFeeCap == nil {
gasFeeCap = new(big.Int).Add( gasFeeCap = new(big.Int).Add(
gasTipCap, gasTipCap,
new(big.Int).Mul(head.BaseFee, big.NewInt(2)), new(big.Int).Mul(head.BaseFee, big.NewInt(basefeeWiggleMultiplier)),
) )
} }
if gasFeeCap.Cmp(gasTipCap) < 0 { if gasFeeCap.Cmp(gasTipCap) < 0 {

View file

@ -115,7 +115,6 @@ func (mc *mockPendingCaller) PendingCallContract(ctx context.Context, call ether
} }
func TestPassingBlockNumber(t *testing.T) { func TestPassingBlockNumber(t *testing.T) {
mc := &mockPendingCaller{ mc := &mockPendingCaller{
mockCaller: &mockCaller{ mockCaller: &mockCaller{
codeAtBytes: []byte{1, 2, 3}, codeAtBytes: []byte{1, 2, 3},

View file

@ -73,7 +73,6 @@ func typeCheck(t Type, value reflect.Value) error {
} else { } else {
return nil return nil
} }
} }
// typeErr returns a formatted type casting error. // typeErr returns a formatted type casting error.

View file

@ -161,7 +161,6 @@ func TestEventMultiValueWithArrayUnpack(t *testing.T) {
} }
func TestEventTupleUnpack(t *testing.T) { func TestEventTupleUnpack(t *testing.T) {
type EventTransfer struct { type EventTransfer struct {
Value *big.Int Value *big.Int
} }

View file

@ -99,7 +99,7 @@ func mustArrayToByteSlice(value reflect.Value) reflect.Value {
func set(dst, src reflect.Value) error { func set(dst, src reflect.Value) error {
dstType, srcType := dst.Type(), src.Type() dstType, srcType := dst.Type(), src.Type()
switch { switch {
case dstType.Kind() == reflect.Interface && dst.Elem().IsValid(): case dstType.Kind() == reflect.Interface && dst.Elem().IsValid() && (dst.Elem().Type().Kind() == reflect.Ptr || dst.Elem().CanSet()):
return set(dst.Elem(), src) return set(dst.Elem(), src)
case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}): case dstType.Kind() == reflect.Ptr && dstType.Elem() != reflect.TypeOf(big.Int{}):
return set(dst.Elem(), src) return set(dst.Elem(), src)
@ -220,7 +220,6 @@ func mapArgNamesToStructFields(argNames []string, value reflect.Value) (map[stri
// second round ~~~ // second round ~~~
for _, argName := range argNames { for _, argName := range argNames {
structFieldName := ToCamelCase(argName) structFieldName := ToCamelCase(argName)
if structFieldName == "" { if structFieldName == "" {

View file

@ -32,7 +32,7 @@ type reflectTest struct {
var reflectTests = []reflectTest{ var reflectTests = []reflectTest{
{ {
name: "OneToOneCorrespondance", name: "OneToOneCorrespondence",
args: []string{"fieldA"}, args: []string{"fieldA"},
struc: struct { struc: struct {
FieldA int `abi:"fieldA"` FieldA int `abi:"fieldA"`

View file

@ -115,7 +115,6 @@ func ReadFixedBytes(t Type, word []byte) (interface{}, error) {
reflect.Copy(array, reflect.ValueOf(word[0:t.Size])) reflect.Copy(array, reflect.ValueOf(word[0:t.Size]))
return array.Interface(), nil return array.Interface(), nil
} }
// forEachUnpack iteratively unpack elements. // forEachUnpack iteratively unpack elements.

View file

@ -352,6 +352,11 @@ func TestMethodMultiReturn(t *testing.T) {
&[]interface{}{&expected.Int, &expected.String}, &[]interface{}{&expected.Int, &expected.String},
"", "",
"Can unpack into a slice", "Can unpack into a slice",
}, {
&[]interface{}{&bigint, ""},
&[]interface{}{&expected.Int, expected.String},
"",
"Can unpack into a slice without indirection",
}, { }, {
&[2]interface{}{&bigint, new(string)}, &[2]interface{}{&bigint, new(string)},
&[2]interface{}{&expected.Int, &expected.String}, &[2]interface{}{&expected.Int, &expected.String},

View file

@ -318,7 +318,7 @@ func waitForAccounts(wantAccounts []accounts.Account, ks *KeyStore) error {
func TestUpdatedKeyfileContents(t *testing.T) { func TestUpdatedKeyfileContents(t *testing.T) {
t.Parallel() t.Parallel()
// Create a temporary kesytore to test with // Create a temporary keystore to test with
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int())) dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-updatedkeyfilecontents-test-%d-%d", os.Getpid(), rand.Int()))
ks := NewKeyStore(dir, LightScryptN, LightScryptP) ks := NewKeyStore(dir, LightScryptN, LightScryptP)

View file

@ -39,7 +39,7 @@ type fileCache struct {
func (fc *fileCache) scan(keyDir string) (mapset.Set, mapset.Set, mapset.Set, error) { func (fc *fileCache) scan(keyDir string) (mapset.Set, mapset.Set, mapset.Set, error) {
t0 := time.Now() t0 := time.Now()
// List all the failes from the keystore folder // List all the files from the keystore folder
files, err := os.ReadDir(keyDir) files, err := os.ReadDir(keyDir)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
@ -61,7 +61,7 @@ func (fc *fileCache) scan(keyDir string) (mapset.Set, mapset.Set, mapset.Set, er
log.Trace("Ignoring file on account scan", "path", path) log.Trace("Ignoring file on account scan", "path", path)
continue continue
} }
// Gather the set of all and fresly modified files // Gather the set of all and freshly modified files
all.Add(path) all.Add(path)
info, err := fi.Info() info, err := fi.Info()

View file

@ -214,7 +214,7 @@ func TestSignRace(t *testing.T) {
// Tests that the wallet notifier loop starts and stops correctly based on the // Tests that the wallet notifier loop starts and stops correctly based on the
// addition and removal of wallet event subscriptions. // addition and removal of wallet event subscriptions.
func TestWalletNotifierLifecycle(t *testing.T) { func TestWalletNotifierLifecycle(t *testing.T) {
// Create a temporary kesytore to test with // Create a temporary keystore to test with
_, ks := tmpKeyStore(t, false) _, ks := tmpKeyStore(t, false)
// Ensure that the notification updater is not running yet // Ensure that the notification updater is not running yet
@ -377,7 +377,6 @@ func TestImportExport(t *testing.T) {
if _, err = ks2.Import(json, "new", "new"); err == nil { if _, err = ks2.Import(json, "new", "new"); err == nil {
t.Errorf("importing a key twice succeeded") t.Errorf("importing a key twice succeeded")
} }
} }
// TestImportRace tests the keystore on races. // TestImportRace tests the keystore on races.
@ -402,7 +401,6 @@ func TestImportRace(t *testing.T) {
if _, err := ks2.Import(json, "new", "new"); err != nil { if _, err := ks2.Import(json, "new", "new"); err != nil {
atomic.AddUint32(&atom, 1) atomic.AddUint32(&atom, 1)
} }
}() }()
} }
wg.Wait() wg.Wait()

View file

@ -138,7 +138,6 @@ func (ks keyStorePassphrase) JoinPath(filename string) string {
// Encryptdata encrypts the data given as 'data' with the password 'auth'. // Encryptdata encrypts the data given as 'data' with the password 'auth'.
func EncryptDataV3(data, auth []byte, scryptN, scryptP int) (CryptoJSON, error) { func EncryptDataV3(data, auth []byte, scryptN, scryptP int) (CryptoJSON, error) {
salt := make([]byte, 32) salt := make([]byte, 32)
if _, err := io.ReadFull(rand.Reader, salt); err != nil { if _, err := io.ReadFull(rand.Reader, salt); err != nil {
panic("reading from crypto/rand failed: " + err.Error()) panic("reading from crypto/rand failed: " + err.Error())
@ -341,7 +340,6 @@ func getKDFKey(cryptoJSON CryptoJSON, auth string) ([]byte, error) {
r := ensureInt(cryptoJSON.KDFParams["r"]) r := ensureInt(cryptoJSON.KDFParams["r"])
p := ensureInt(cryptoJSON.KDFParams["p"]) p := ensureInt(cryptoJSON.KDFParams["p"])
return scrypt.Key(authArray, salt, n, r, p, dkLen) return scrypt.Key(authArray, salt, n, r, p, dkLen)
} else if cryptoJSON.KDF == "pbkdf2" { } else if cryptoJSON.KDF == "pbkdf2" {
c := ensureInt(cryptoJSON.KDFParams["c"]) c := ensureInt(cryptoJSON.KDFParams["c"])
prf := cryptoJSON.KDFParams["prf"].(string) prf := cryptoJSON.KDFParams["prf"].(string)

View file

@ -196,10 +196,10 @@ func (w *trezorDriver) trezorDerive(derivationPath []uint32) (common.Address, er
if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil { if _, err := w.trezorExchange(&trezor.EthereumGetAddress{AddressN: derivationPath}, address); err != nil {
return common.Address{}, err return common.Address{}, err
} }
if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary fomats if addr := address.GetAddressBin(); len(addr) > 0 { // Older firmwares use binary formats
return common.BytesToAddress(addr), nil return common.BytesToAddress(addr), nil
} }
if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal fomats if addr := address.GetAddressHex(); len(addr) > 0 { // Newer firmwares use hexadecimal formats
return common.HexToAddress(addr), nil return common.HexToAddress(addr), nil
} }
return common.Address{}, errors.New("missing derived address") return common.Address{}, errors.New("missing derived address")

View file

@ -380,7 +380,7 @@ func (w *wallet) selfDerive() {
// of legacy-ledger, the first account on the legacy-path will // of legacy-ledger, the first account on the legacy-path will
// be shown to the user, even if we don't actively track it // be shown to the user, even if we don't actively track it
if i < len(nextAddrs)-1 { if i < len(nextAddrs)-1 {
w.log.Info("Skipping trakcking first account on legacy path, use personal.deriveAccount(<url>,<path>, false) to track", w.log.Info("Skipping tracking first account on legacy path, use personal.deriveAccount(<url>,<path>, false) to track",
"path", path, "address", nextAddrs[i]) "path", path, "address", nextAddrs[i])
break break
} }
@ -526,7 +526,6 @@ func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error)
// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed // SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) { func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
// Unless we are doing 712 signing, simply dispatch to signHash // Unless we are doing 712 signing, simply dispatch to signHash
if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) { if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) {
return w.signHash(account, crypto.Keccak256(data)) return w.signHash(account, crypto.Keccak256(data))

View file

@ -1,19 +1,19 @@
# This file contains sha256 checksums of optional build dependencies. # This file contains sha256 checksums of optional build dependencies.
4525aa6b0e3cecb57845f4060a7075aafc9ab752bb7b6b4cf8a212d43078e1e4 go1.18.4.src.tar.gz 9920d3306a1ac536cdd2c796d6cb3c54bc559c226fc3cc39c32f1e0bd7f50d2a go1.18.5.src.tar.gz
315e1a2b21a827c68da1b7f492b5dcbe81d8df8a79ebe50922df9588893f87f0 go1.18.4.darwin-amd64.tar.gz 828eeca8b5abea3e56921df8fa4b1101380a5ebcfee10acbc8ffe7ec0bf5876b go1.18.5.darwin-amd64.tar.gz
04eed623d5143ffa44965b618b509e0beccccfd3a4a1bfebc0cdbcf906046769 go1.18.4.darwin-arm64.tar.gz 923a377c6fc9a2c789f5db61c24b8f64133f7889056897449891f256af34065f go1.18.5.darwin-arm64.tar.gz
e5244fdcd6b6eaf785dbd8c6e02b4804a4d00409e7edecc63cd59fc8f37c34c5 go1.18.4.freebsd-386.tar.gz c3d90264a706e2d88cfb44126dc6f0d008a48f00732e04bc377cea1a2b716a7c go1.18.5.freebsd-386.tar.gz
fb00f8aaffcc80e0a2bd39db1d8e8e21ef0a691c564f7b7601383dd6adad4042 go1.18.4.freebsd-amd64.tar.gz 0de23843c568d388bc0f0e390a8966938cccaae0d74b698325f7175bac04e0c6 go1.18.5.freebsd-amd64.tar.gz
418232d905e18ece6cb13c4884bb1c68963d7d3b4d889671b3e5be8bd4059862 go1.18.4.linux-386.tar.gz 0c44f85d146c6f98c34e8ff436a42af22e90e36fe232d3d9d3101f23fd61362b go1.18.5.linux-386.tar.gz
c9b099b68d93f5c5c8a8844a89f8db07eaa58270e3a1e01804f17f4cf8df02f5 go1.18.4.linux-amd64.tar.gz 9e5de37f9c49942c601b191ac5fba404b868bfc21d446d6960acc12283d6e5f2 go1.18.5.linux-amd64.tar.gz
35014d92b50d97da41dade965df7ebeb9a715da600206aa59ce1b2d05527421f go1.18.4.linux-arm64.tar.gz 006f6622718212363fa1ff004a6ab4d87bbbe772ec5631bab7cac10be346e4f1 go1.18.5.linux-arm64.tar.gz
7dfeab572e49638b0f3d9901457f0622c27b73301c2b99db9f5e9568ff40460c go1.18.4.linux-armv6l.tar.gz d5ac34ac5f060a5274319aa04b7b11e41b123bd7887d64efb5f44ead236957af go1.18.5.linux-armv6l.tar.gz
f80acc4dc054ddc89ccc4869664e331bf16e0ac6e07830e94554162e66f66961 go1.18.4.linux-ppc64le.tar.gz 2e37fb9c7cbaedd4e729492d658aa4cde821fc94117391a8105c13b25ca1c84b go1.18.5.linux-ppc64le.tar.gz
7e932f36e8f347feea2e706dcd32c1a464b1e5767ab2928ae460a37a975fe4a3 go1.18.4.linux-s390x.tar.gz e3d536e7873639f85353e892444f83b14cb6670603961f215986ae8e28e8e07a go1.18.5.linux-s390x.tar.gz
6343010a13ab783e553786b3cc3b4d63080128f61cf1e963505139c71ca66a0d go1.18.4.windows-386.zip 7b3142ec0c5db991e7f73a231662a92429b90ee151fe47557acb566d8d9ae4d3 go1.18.5.windows-386.zip
dfb93c517e050ba0cfc066802b38a8e7cda2ef666efd634859356b33f543cc49 go1.18.4.windows-amd64.zip 73753620602d4b4469770040c53db55e5dd6af2ad07ecc18f71f164c3224eaad go1.18.5.windows-amd64.zip
7d0d7b73592019d276f2bd44ee3cda0d8bd99356fdbf04fdb40c263518108ae4 go1.18.4.windows-arm64.zip 4d154626affff12ef73ea1017af0e5b52dbc839ef92f6f9e76cf4f71278a5744 go1.18.5.windows-arm64.zip
658078aaaf7608693f37c4cf1380b2af418ab8b2d23fdb33e7e2d4339328590e golangci-lint-1.46.2-darwin-amd64.tar.gz 658078aaaf7608693f37c4cf1380b2af418ab8b2d23fdb33e7e2d4339328590e golangci-lint-1.46.2-darwin-amd64.tar.gz
81f9b4afd62ec5e612ef8bc3b1d612a88b56ff289874831845cdad394427385f golangci-lint-1.46.2-darwin-arm64.tar.gz 81f9b4afd62ec5e612ef8bc3b1d612a88b56ff289874831845cdad394427385f golangci-lint-1.46.2-darwin-arm64.tar.gz

View file

@ -149,7 +149,7 @@ var (
// This is the version of go that will be downloaded by // This is the version of go that will be downloaded by
// //
// go run ci.go install -dlgo // go run ci.go install -dlgo
dlgoVersion = "1.18.4" dlgoVersion = "1.18.5"
) )
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin")) var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@ -203,6 +203,7 @@ func doInstall(cmdline []string) {
dlgo = flag.Bool("dlgo", false, "Download Go and build with it") dlgo = flag.Bool("dlgo", false, "Download Go and build with it")
arch = flag.String("arch", "", "Architecture to cross build for") arch = flag.String("arch", "", "Architecture to cross build for")
cc = flag.String("cc", "", "C compiler to cross build with") cc = flag.String("cc", "", "C compiler to cross build with")
staticlink = flag.Bool("static", false, "Create statically-linked executable")
) )
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
@ -213,9 +214,12 @@ func doInstall(cmdline []string) {
tc.Root = build.DownloadGo(csdb, dlgoVersion) tc.Root = build.DownloadGo(csdb, dlgoVersion)
} }
// Disable CLI markdown doc generation in release builds.
buildTags := []string{"urfave_cli_no_docs"}
// Configure the build. // Configure the build.
env := build.Env() env := build.Env()
gobuild := tc.Go("build", buildFlags(env)...) gobuild := tc.Go("build", buildFlags(env, *staticlink, buildTags)...)
// arm64 CI builders are memory-constrained and can't handle concurrent builds, // arm64 CI builders are memory-constrained and can't handle concurrent builds,
// better disable it. This check isn't the best, it should probably // better disable it. This check isn't the best, it should probably
@ -224,9 +228,6 @@ func doInstall(cmdline []string) {
gobuild.Args = append(gobuild.Args, "-p", "1") gobuild.Args = append(gobuild.Args, "-p", "1")
} }
// Disable CLI markdown doc generation in release builds.
gobuild.Args = append(gobuild.Args, "-tags", "urfave_cli_no_docs")
// We use -trimpath to avoid leaking local paths into the built executables. // We use -trimpath to avoid leaking local paths into the built executables.
gobuild.Args = append(gobuild.Args, "-trimpath") gobuild.Args = append(gobuild.Args, "-trimpath")
@ -251,7 +252,7 @@ func doInstall(cmdline []string) {
} }
// buildFlags returns the go tool flags for building. // buildFlags returns the go tool flags for building.
func buildFlags(env build.Environment) (flags []string) { func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (flags []string) {
var ld []string var ld []string
if env.Commit != "" { if env.Commit != "" {
ld = append(ld, "-X", "main.gitCommit="+env.Commit) ld = append(ld, "-X", "main.gitCommit="+env.Commit)
@ -262,14 +263,24 @@ func buildFlags(env build.Environment) (flags []string) {
if runtime.GOOS == "darwin" { if runtime.GOOS == "darwin" {
ld = append(ld, "-s") ld = append(ld, "-s")
} }
if runtime.GOOS == "linux" {
// Enforce the stacksize to 8M, which is the case on most platforms apart from // Enforce the stacksize to 8M, which is the case on most platforms apart from
// alpine Linux. // alpine Linux.
if runtime.GOOS == "linux" { extld := []string{"-Wl,-z,stack-size=0x800000"}
ld = append(ld, "-extldflags", "-Wl,-z,stack-size=0x800000") if staticLinking {
extld = append(extld, "-static")
// Under static linking, use of certain glibc features must be
// disabled to avoid shared library dependencies.
buildTags = append(buildTags, "osusergo", "netgo")
}
ld = append(ld, "-extldflags", "'"+strings.Join(extld, " ")+"'")
} }
if len(ld) > 0 { if len(ld) > 0 {
flags = append(flags, "-ldflags", strings.Join(ld, " ")) flags = append(flags, "-ldflags", strings.Join(ld, " "))
} }
if len(buildTags) > 0 {
flags = append(flags, "-tags", strings.Join(buildTags, ","))
}
return flags return flags
} }
@ -597,7 +608,7 @@ func doDocker(cmdline []string) {
} }
if mismatch { if mismatch {
// Build numbers mismatching, retry in a short time to // Build numbers mismatching, retry in a short time to
// avoid concurrent failes in both publisher images. If // avoid concurrent fails in both publisher images. If
// however the retry failed too, it means the concurrent // however the retry failed too, it means the concurrent
// builder is still crunching, let that do the publish. // builder is still crunching, let that do the publish.
if i == 0 { if i == 0 {
@ -971,7 +982,10 @@ func doWindowsInstaller(cmdline []string) {
if env.Commit != "" { if env.Commit != "" {
version[2] += "-" + env.Commit[:8] version[2] += "-" + env.Commit[:8]
} }
installer, _ := filepath.Abs("geth-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe") installer, err := filepath.Abs("geth-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe")
if err != nil {
log.Fatalf("Failed to convert installer file path: %v", err)
}
build.MustRunCommand("makensis.exe", build.MustRunCommand("makensis.exe",
"/DOUTPUTFILE="+installer, "/DOUTPUTFILE="+installer,
"/DMAJORVERSION="+version[0], "/DMAJORVERSION="+version[0],

View file

@ -342,7 +342,10 @@ func isGenerated(file string) bool {
} }
defer fd.Close() defer fd.Close()
buf := make([]byte, 2048) buf := make([]byte, 2048)
n, _ := fd.Read(buf) n, err := fd.Read(buf)
if err != nil {
return false
}
buf = buf[:n] buf = buf[:n]
for _, l := range bytes.Split(buf, []byte("\n")) { for _, l := range bytes.Split(buf, []byte("\n")) {
if bytes.HasPrefix(l, []byte("// Code generated")) { if bytes.HasPrefix(l, []byte("// Code generated")) {

View file

@ -759,7 +759,6 @@ func confirm(text string) bool {
} }
func testExternalUI(api *core.SignerAPI) { func testExternalUI(api *core.SignerAPI) {
ctx := context.WithValue(context.Background(), "remote", "clef binary") ctx := context.WithValue(context.Background(), "remote", "clef binary")
ctx = context.WithValue(ctx, "scheme", "in-proc") ctx = context.WithValue(ctx, "scheme", "in-proc")
ctx = context.WithValue(ctx, "local", "main") ctx = context.WithValue(ctx, "local", "main")
@ -859,7 +858,6 @@ func testExternalUI(api *core.SignerAPI) {
expectDeny("signdata - text", err) expectDeny("signdata - text", err)
} }
{ // Sign transaction { // Sign transaction
api.UI.ShowInfo("Please reject next transaction") api.UI.ShowInfo("Please reject next transaction")
time.Sleep(delay) time.Sleep(delay)
data := hexutil.Bytes([]byte{}) data := hexutil.Bytes([]byte{})
@ -902,7 +900,6 @@ func testExternalUI(api *core.SignerAPI) {
} }
result := fmt.Sprintf("Tests completed. %d errors:\n%s\n", len(errs), strings.Join(errs, "\n")) result := fmt.Sprintf("Tests completed. %d errors:\n%s\n", len(errs), strings.Join(errs, "\n"))
api.UI.ShowInfo(result) api.UI.ShowInfo(result)
} }
type encryptedSeedStorage struct { type encryptedSeedStorage struct {
@ -939,7 +936,6 @@ func decryptSeed(keyjson []byte, auth string) ([]byte, error) {
// GenDoc outputs examples of all structures used in json-rpc communication // GenDoc outputs examples of all structures used in json-rpc communication
func GenDoc(ctx *cli.Context) error { func GenDoc(ctx *cli.Context) error {
var ( var (
a = common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef") a = common.HexToAddress("0xdeadbeef000000000000000000000000deadbeef")
b = common.HexToAddress("0x1111111122222222222233333333334444444444") b = common.HexToAddress("0x1111111122222222222233333333334444444444")
@ -1049,7 +1045,6 @@ func GenDoc(ctx *cli.Context) error {
var tx types.Transaction var tx types.Transaction
tx.UnmarshalBinary(rlpdata) tx.UnmarshalBinary(rlpdata)
add("OnApproved - SignTransactionResult", desc, &ethapi.SignTransactionResult{Raw: rlpdata, Tx: &tx}) add("OnApproved - SignTransactionResult", desc, &ethapi.SignTransactionResult{Raw: rlpdata, Tx: &tx})
} }
{ // User input { // User input
add("UserInputRequest", "Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free)", add("UserInputRequest", "Sent when clef needs the user to provide data. If 'password' is true, the input field should be treated accordingly (echo-free)",

View file

@ -134,7 +134,6 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
ttl := rootTTL ttl := rootTTL
if path != name { if path != name {
ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare
} }
record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl} record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}
_, err = c.CreateDNSRecord(context.Background(), c.zoneID, record) _, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)

View file

@ -96,12 +96,12 @@ func (c *Chain) Head() *types.Block {
return c.blocks[c.Len()-1] return c.blocks[c.Len()-1]
} }
func (c *Chain) GetHeaders(req GetBlockHeaders) (BlockHeaders, error) { func (c *Chain) GetHeaders(req *GetBlockHeaders) ([]*types.Header, error) {
if req.Amount < 1 { if req.Amount < 1 {
return nil, fmt.Errorf("no block headers requested") return nil, fmt.Errorf("no block headers requested")
} }
headers := make(BlockHeaders, req.Amount) headers := make([]*types.Header, req.Amount)
var blockNumber uint64 var blockNumber uint64
// range over blocks to check if our chain has the requested header // range over blocks to check if our chain has the requested header
@ -119,7 +119,6 @@ func (c *Chain) GetHeaders(req GetBlockHeaders) (BlockHeaders, error) {
for i := 1; i < int(req.Amount); i++ { for i := 1; i < int(req.Amount); i++ {
blockNumber -= (1 - req.Skip) blockNumber -= (1 - req.Skip)
headers[i] = c.blocks[blockNumber].Header() headers[i] = c.blocks[blockNumber].Header()
} }
return headers, nil return headers, nil
@ -140,7 +139,7 @@ func loadChain(chainfile string, genesis string) (*Chain, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
gblock := gen.ToBlock(nil) gblock := gen.ToBlock()
blocks, err := blocksFromFile(chainfile, gblock) blocks, err := blocksFromFile(chainfile, gblock)
if err != nil { if err != nil {

View file

@ -21,6 +21,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -140,18 +141,18 @@ func TestChain_GetHeaders(t *testing.T) {
var tests = []struct { var tests = []struct {
req GetBlockHeaders req GetBlockHeaders
expected BlockHeaders expected []*types.Header
}{ }{
{ {
req: GetBlockHeaders{ req: GetBlockHeaders{
Origin: eth.HashOrNumber{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Number: uint64(2), Origin: eth.HashOrNumber{Number: uint64(2)},
},
Amount: uint64(5), Amount: uint64(5),
Skip: 1, Skip: 1,
Reverse: false, Reverse: false,
}, },
expected: BlockHeaders{ },
expected: []*types.Header{
chain.blocks[2].Header(), chain.blocks[2].Header(),
chain.blocks[4].Header(), chain.blocks[4].Header(),
chain.blocks[6].Header(), chain.blocks[6].Header(),
@ -161,14 +162,14 @@ func TestChain_GetHeaders(t *testing.T) {
}, },
{ {
req: GetBlockHeaders{ req: GetBlockHeaders{
Origin: eth.HashOrNumber{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Number: uint64(chain.Len() - 1), Origin: eth.HashOrNumber{Number: uint64(chain.Len() - 1)},
},
Amount: uint64(3), Amount: uint64(3),
Skip: 0, Skip: 0,
Reverse: true, Reverse: true,
}, },
expected: BlockHeaders{ },
expected: []*types.Header{
chain.blocks[chain.Len()-1].Header(), chain.blocks[chain.Len()-1].Header(),
chain.blocks[chain.Len()-2].Header(), chain.blocks[chain.Len()-2].Header(),
chain.blocks[chain.Len()-3].Header(), chain.blocks[chain.Len()-3].Header(),
@ -176,14 +177,14 @@ func TestChain_GetHeaders(t *testing.T) {
}, },
{ {
req: GetBlockHeaders{ req: GetBlockHeaders{
Origin: eth.HashOrNumber{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Hash: chain.Head().Hash(), Origin: eth.HashOrNumber{Hash: chain.Head().Hash()},
},
Amount: uint64(1), Amount: uint64(1),
Skip: 0, Skip: 0,
Reverse: false, Reverse: false,
}, },
expected: BlockHeaders{ },
expected: []*types.Header{
chain.Head().Header(), chain.Head().Header(),
}, },
}, },
@ -191,7 +192,7 @@ func TestChain_GetHeaders(t *testing.T) {
for i, tt := range tests { for i, tt := range tests {
t.Run(strconv.Itoa(i), func(t *testing.T) { t.Run(strconv.Itoa(i), func(t *testing.T) {
headers, err := chain.GetHeaders(tt.req) headers, err := chain.GetHeaders(&tt.req)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View file

@ -43,21 +43,6 @@ var (
timeout = 20 * time.Second timeout = 20 * time.Second
) )
// Is_66 checks if the node supports the eth66 protocol version,
// and if not, exists the test suite
func (s *Suite) Is_66(t *utesting.T) {
conn, err := s.dial66()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
if err := conn.handshake(); err != nil {
t.Fatalf("handshake failed: %v", err)
}
if conn.negotiatedProtoVersion < 66 {
t.Fail()
}
}
// dial attempts to dial the given node and perform a handshake, // dial attempts to dial the given node and perform a handshake,
// returning the created Conn if successful. // returning the created Conn if successful.
func (s *Suite) dial() (*Conn, error) { func (s *Suite) dial() (*Conn, error) {
@ -76,31 +61,16 @@ func (s *Suite) dial() (*Conn, error) {
} }
// set default p2p capabilities // set default p2p capabilities
conn.caps = []p2p.Cap{ conn.caps = []p2p.Cap{
{Name: "eth", Version: 64}, {Name: "eth", Version: 66},
{Name: "eth", Version: 65}, {Name: "eth", Version: 67},
} }
conn.ourHighestProtoVersion = 65 conn.ourHighestProtoVersion = 67
return &conn, nil return &conn, nil
} }
// dial66 attempts to dial the given node and perform a handshake, // dialSnap creates a connection with snap/1 capability.
// returning the created Conn with additional eth66 capabilities if
// successful
func (s *Suite) dial66() (*Conn, error) {
conn, err := s.dial()
if err != nil {
return nil, fmt.Errorf("dial failed: %v", err)
}
conn.caps = append(conn.caps, p2p.Cap{Name: "eth", Version: 66})
conn.ourHighestProtoVersion = 66
return conn, nil
}
// dial66 attempts to dial the given node and perform a handshake,
// returning the created Conn with additional snap/1 capabilities if
// successful.
func (s *Suite) dialSnap() (*Conn, error) { func (s *Suite) dialSnap() (*Conn, error) {
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
return nil, fmt.Errorf("dial failed: %v", err) return nil, fmt.Errorf("dial failed: %v", err)
} }
@ -235,60 +205,40 @@ loop:
// createSendAndRecvConns creates two connections, one for sending messages to the // createSendAndRecvConns creates two connections, one for sending messages to the
// node, and one for receiving messages from the node. // node, and one for receiving messages from the node.
func (s *Suite) createSendAndRecvConns(isEth66 bool) (*Conn, *Conn, error) { func (s *Suite) createSendAndRecvConns() (*Conn, *Conn, error) {
var ( sendConn, err := s.dial()
sendConn *Conn
recvConn *Conn
err error
)
if isEth66 {
sendConn, err = s.dial66()
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("dial failed: %v", err) return nil, nil, fmt.Errorf("dial failed: %v", err)
} }
recvConn, err = s.dial66() recvConn, err := s.dial()
if err != nil { if err != nil {
sendConn.Close() sendConn.Close()
return nil, nil, fmt.Errorf("dial failed: %v", err) return nil, nil, fmt.Errorf("dial failed: %v", err)
} }
} else {
sendConn, err = s.dial()
if err != nil {
return nil, nil, fmt.Errorf("dial failed: %v", err)
}
recvConn, err = s.dial()
if err != nil {
sendConn.Close()
return nil, nil, fmt.Errorf("dial failed: %v", err)
}
}
return sendConn, recvConn, nil return sendConn, recvConn, nil
} }
func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
if c.negotiatedProtoVersion == 66 {
_, msg := c.readAndServe66(chain, timeout)
return msg
}
return c.readAndServe65(chain, timeout)
}
// readAndServe serves GetBlockHeaders requests while waiting // readAndServe serves GetBlockHeaders requests while waiting
// on another message from the node. // on another message from the node.
func (c *Conn) readAndServe65(chain *Chain, timeout time.Duration) Message { func (c *Conn) readAndServe(chain *Chain, timeout time.Duration) Message {
start := time.Now() start := time.Now()
for time.Since(start) < timeout { for time.Since(start) < timeout {
c.SetReadDeadline(time.Now().Add(5 * time.Second)) c.SetReadDeadline(time.Now().Add(10 * time.Second))
switch msg := c.Read().(type) {
msg := c.Read()
switch msg := msg.(type) {
case *Ping: case *Ping:
c.Write(&Pong{}) c.Write(&Pong{})
case *GetBlockHeaders: case *GetBlockHeaders:
req := *msg headers, err := chain.GetHeaders(msg)
headers, err := chain.GetHeaders(req)
if err != nil { if err != nil {
return errorf("could not get headers for inbound header request: %v", err) return errorf("could not get headers for inbound header request: %v", err)
} }
if err := c.Write(headers); err != nil { resp := &BlockHeaders{
RequestId: msg.ReqID(),
BlockHeadersPacket: eth.BlockHeadersPacket(headers),
}
if err := c.Write(resp); err != nil {
return errorf("could not write to connection: %v", err) return errorf("could not write to connection: %v", err)
} }
default: default:
@ -298,54 +248,25 @@ func (c *Conn) readAndServe65(chain *Chain, timeout time.Duration) Message {
return errorf("no message received within %v", timeout) return errorf("no message received within %v", timeout)
} }
// readAndServe66 serves eth66 GetBlockHeaders requests while waiting
// on another message from the node.
func (c *Conn) readAndServe66(chain *Chain, timeout time.Duration) (uint64, Message) {
start := time.Now()
for time.Since(start) < timeout {
c.SetReadDeadline(time.Now().Add(10 * time.Second))
reqID, msg := c.Read66()
switch msg := msg.(type) {
case *Ping:
c.Write(&Pong{})
case GetBlockHeaders:
headers, err := chain.GetHeaders(msg)
if err != nil {
return 0, errorf("could not get headers for inbound header request: %v", err)
}
resp := &eth.BlockHeadersPacket66{
RequestId: reqID,
BlockHeadersPacket: eth.BlockHeadersPacket(headers),
}
if err := c.Write66(resp, BlockHeaders{}.Code()); err != nil {
return 0, errorf("could not write to connection: %v", err)
}
default:
return reqID, msg
}
}
return 0, errorf("no message received within %v", timeout)
}
// headersRequest executes the given `GetBlockHeaders` request. // headersRequest executes the given `GetBlockHeaders` request.
func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, isEth66 bool, reqID uint64) (BlockHeaders, error) { func (c *Conn) headersRequest(request *GetBlockHeaders, chain *Chain, reqID uint64) ([]*types.Header, error) {
defer c.SetReadDeadline(time.Time{}) defer c.SetReadDeadline(time.Time{})
c.SetReadDeadline(time.Now().Add(20 * time.Second)) c.SetReadDeadline(time.Now().Add(20 * time.Second))
// if on eth66 connection, perform eth66 GetBlockHeaders request
if isEth66 { // write request
return getBlockHeaders66(chain, c, request, reqID) request.RequestId = reqID
}
if err := c.Write(request); err != nil { if err := c.Write(request); err != nil {
return nil, err return nil, fmt.Errorf("could not write to connection: %v", err)
} }
switch msg := c.readAndServe(chain, timeout).(type) {
case *BlockHeaders: // wait for response
return *msg, nil msg := c.waitForResponse(chain, timeout, request.RequestId)
default: resp, ok := msg.(*BlockHeaders)
return nil, fmt.Errorf("invalid message: %s", pretty.Sdump(msg)) if !ok {
return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
} }
headers := []*types.Header(resp.BlockHeadersPacket)
return headers, nil
} }
func (c *Conn) snapRequest(msg Message, id uint64, chain *Chain) (Message, error) { func (c *Conn) snapRequest(msg Message, id uint64, chain *Chain) (Message, error) {
@ -357,28 +278,8 @@ func (c *Conn) snapRequest(msg Message, id uint64, chain *Chain) (Message, error
return c.ReadSnap(id) return c.ReadSnap(id)
} }
// getBlockHeaders66 executes the given `GetBlockHeaders` request over the eth66 protocol.
func getBlockHeaders66(chain *Chain, conn *Conn, request *GetBlockHeaders, id uint64) (BlockHeaders, error) {
// write request
packet := eth.GetBlockHeadersPacket(*request)
req := &eth.GetBlockHeadersPacket66{
RequestId: id,
GetBlockHeadersPacket: &packet,
}
if err := conn.Write66(req, GetBlockHeaders{}.Code()); err != nil {
return nil, fmt.Errorf("could not write to connection: %v", err)
}
// wait for response
msg := conn.waitForResponse(chain, timeout, req.RequestId)
headers, ok := msg.(BlockHeaders)
if !ok {
return nil, fmt.Errorf("unexpected message received: %s", pretty.Sdump(msg))
}
return headers, nil
}
// headersMatch returns whether the received headers match the given request // headersMatch returns whether the received headers match the given request
func headersMatch(expected BlockHeaders, headers BlockHeaders) bool { func headersMatch(expected []*types.Header, headers []*types.Header) bool {
return reflect.DeepEqual(expected, headers) return reflect.DeepEqual(expected, headers)
} }
@ -386,8 +287,8 @@ func headersMatch(expected BlockHeaders, headers BlockHeaders) bool {
// request ID is received. // request ID is received.
func (c *Conn) waitForResponse(chain *Chain, timeout time.Duration, requestID uint64) Message { func (c *Conn) waitForResponse(chain *Chain, timeout time.Duration, requestID uint64) Message {
for { for {
id, msg := c.readAndServe66(chain, timeout) msg := c.readAndServe(chain, timeout)
if id == requestID { if msg.ReqID() == requestID {
return msg return msg
} }
} }
@ -395,9 +296,9 @@ func (c *Conn) waitForResponse(chain *Chain, timeout time.Duration, requestID ui
// sendNextBlock broadcasts the next block in the chain and waits // sendNextBlock broadcasts the next block in the chain and waits
// for the node to propagate the block and import it into its chain. // for the node to propagate the block and import it into its chain.
func (s *Suite) sendNextBlock(isEth66 bool) error { func (s *Suite) sendNextBlock() error {
// set up sending and receiving connections // set up sending and receiving connections
sendConn, recvConn, err := s.createSendAndRecvConns(isEth66) sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil { if err != nil {
return err return err
} }
@ -420,7 +321,7 @@ func (s *Suite) sendNextBlock(isEth66 bool) error {
return fmt.Errorf("failed to announce block: %v", err) return fmt.Errorf("failed to announce block: %v", err)
} }
// wait for client to update its chain // wait for client to update its chain
if err = s.waitForBlockImport(recvConn, nextBlock, isEth66); err != nil { if err = s.waitForBlockImport(recvConn, nextBlock); err != nil {
return fmt.Errorf("failed to receive confirmation of block import: %v", err) return fmt.Errorf("failed to receive confirmation of block import: %v", err)
} }
// update test suite chain // update test suite chain
@ -465,29 +366,22 @@ func (s *Suite) waitAnnounce(conn *Conn, blockAnnouncement *NewBlock) error {
} }
} }
func (s *Suite) waitForBlockImport(conn *Conn, block *types.Block, isEth66 bool) error { func (s *Suite) waitForBlockImport(conn *Conn, block *types.Block) error {
defer conn.SetReadDeadline(time.Time{}) defer conn.SetReadDeadline(time.Time{})
conn.SetReadDeadline(time.Now().Add(20 * time.Second)) conn.SetReadDeadline(time.Now().Add(20 * time.Second))
// create request // create request
req := &GetBlockHeaders{ req := &GetBlockHeaders{
Origin: eth.HashOrNumber{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Hash: block.Hash(), Origin: eth.HashOrNumber{Hash: block.Hash()},
},
Amount: 1, Amount: 1,
},
} }
// loop until BlockHeaders response contains desired block, confirming the // loop until BlockHeaders response contains desired block, confirming the
// node imported the block // node imported the block
for { for {
var (
headers BlockHeaders
err error
)
if isEth66 {
requestID := uint64(54) requestID := uint64(54)
headers, err = conn.headersRequest(req, s.chain, eth66, requestID) headers, err := conn.headersRequest(req, s.chain, requestID)
} else {
headers, err = conn.headersRequest(req, s.chain, eth65, 0)
}
if err != nil { if err != nil {
return fmt.Errorf("GetBlockHeader request failed: %v", err) return fmt.Errorf("GetBlockHeader request failed: %v", err)
} }
@ -503,8 +397,8 @@ func (s *Suite) waitForBlockImport(conn *Conn, block *types.Block, isEth66 bool)
} }
} }
func (s *Suite) oldAnnounce(isEth66 bool) error { func (s *Suite) oldAnnounce() error {
sendConn, receiveConn, err := s.createSendAndRecvConns(isEth66) sendConn, receiveConn, err := s.createSendAndRecvConns()
if err != nil { if err != nil {
return err return err
} }
@ -550,23 +444,13 @@ func (s *Suite) oldAnnounce(isEth66 bool) error {
return nil return nil
} }
func (s *Suite) maliciousHandshakes(t *utesting.T, isEth66 bool) error { func (s *Suite) maliciousHandshakes(t *utesting.T) error {
var ( conn, err := s.dial()
conn *Conn
err error
)
if isEth66 {
conn, err = s.dial66()
if err != nil { if err != nil {
return fmt.Errorf("dial failed: %v", err) return fmt.Errorf("dial failed: %v", err)
} }
} else {
conn, err = s.dial()
if err != nil {
return fmt.Errorf("dial failed: %v", err)
}
}
defer conn.Close() defer conn.Close()
// write hello to client // write hello to client
pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:] pub0 := crypto.FromECDSAPub(&conn.ourKey.PublicKey)[1:]
handshakes := []*Hello{ handshakes := []*Hello{
@ -627,18 +511,11 @@ func (s *Suite) maliciousHandshakes(t *utesting.T, isEth66 bool) error {
} }
} }
// dial for the next round // dial for the next round
if isEth66 {
conn, err = s.dial66()
if err != nil {
return fmt.Errorf("dial failed: %v", err)
}
} else {
conn, err = s.dial() conn, err = s.dial()
if err != nil { if err != nil {
return fmt.Errorf("dial failed: %v", err) return fmt.Errorf("dial failed: %v", err)
} }
} }
}
return nil return nil
} }
@ -654,6 +531,7 @@ func (s *Suite) maliciousStatus(conn *Conn) error {
Genesis: s.chain.blocks[0].Hash(), Genesis: s.chain.blocks[0].Hash(),
ForkID: s.chain.ForkID(), ForkID: s.chain.ForkID(),
} }
// get status // get status
msg, err := conn.statusExchange(s.chain, status) msg, err := conn.statusExchange(s.chain, status)
if err != nil { if err != nil {
@ -664,6 +542,7 @@ func (s *Suite) maliciousStatus(conn *Conn) error {
default: default:
return fmt.Errorf("expected status, got: %#v ", msg) return fmt.Errorf("expected status, got: %#v ", msg)
} }
// wait for disconnect // wait for disconnect
switch msg := conn.readAndServe(s.chain, timeout).(type) { switch msg := conn.readAndServe(s.chain, timeout).(type) {
case *Disconnect: case *Disconnect:
@ -675,9 +554,9 @@ func (s *Suite) maliciousStatus(conn *Conn) error {
} }
} }
func (s *Suite) hashAnnounce(isEth66 bool) error { func (s *Suite) hashAnnounce() error {
// create connections // create connections
sendConn, recvConn, err := s.createSendAndRecvConns(isEth66) sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil { if err != nil {
return fmt.Errorf("failed to create connections: %v", err) return fmt.Errorf("failed to create connections: %v", err)
} }
@ -689,6 +568,7 @@ func (s *Suite) hashAnnounce(isEth66 bool) error {
if err := recvConn.peer(s.chain, nil); err != nil { if err := recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err) return fmt.Errorf("peering failed: %v", err)
} }
// create NewBlockHashes announcement // create NewBlockHashes announcement
type anno struct { type anno struct {
Hash common.Hash // Hash of one particular block being announced Hash common.Hash // Hash of one particular block being announced
@ -700,18 +580,11 @@ func (s *Suite) hashAnnounce(isEth66 bool) error {
if err := sendConn.Write(newBlockHash); err != nil { if err := sendConn.Write(newBlockHash); err != nil {
return fmt.Errorf("failed to write to connection: %v", err) return fmt.Errorf("failed to write to connection: %v", err)
} }
// Announcement sent, now wait for a header request // Announcement sent, now wait for a header request
var ( msg := sendConn.Read()
id uint64 blockHeaderReq, ok := msg.(*GetBlockHeaders)
msg Message if !ok {
blockHeaderReq GetBlockHeaders
)
if isEth66 {
id, msg = sendConn.Read66()
switch msg := msg.(type) {
case GetBlockHeaders:
blockHeaderReq = msg
default:
return fmt.Errorf("unexpected %s", pretty.Sdump(msg)) return fmt.Errorf("unexpected %s", pretty.Sdump(msg))
} }
if blockHeaderReq.Amount != 1 { if blockHeaderReq.Amount != 1 {
@ -722,34 +595,14 @@ func (s *Suite) hashAnnounce(isEth66 bool) error {
pretty.Sdump(announcement), pretty.Sdump(announcement),
pretty.Sdump(blockHeaderReq)) pretty.Sdump(blockHeaderReq))
} }
if err := sendConn.Write66(&eth.BlockHeadersPacket66{ err = sendConn.Write(&BlockHeaders{
RequestId: id, RequestId: blockHeaderReq.ReqID(),
BlockHeadersPacket: eth.BlockHeadersPacket{ BlockHeadersPacket: eth.BlockHeadersPacket{nextBlock.Header()},
nextBlock.Header(), })
}, if err != nil {
}, BlockHeaders{}.Code()); err != nil {
return fmt.Errorf("failed to write to connection: %v", err) return fmt.Errorf("failed to write to connection: %v", err)
} }
} else {
msg = sendConn.Read()
switch msg := msg.(type) {
case *GetBlockHeaders:
blockHeaderReq = *msg
default:
return fmt.Errorf("unexpected %s", pretty.Sdump(msg))
}
if blockHeaderReq.Amount != 1 {
return fmt.Errorf("unexpected number of block headers requested: %v", blockHeaderReq.Amount)
}
if blockHeaderReq.Origin.Hash != announcement.Hash {
return fmt.Errorf("unexpected block header requested. Announced:\n %v\n Remote request:\n%v",
pretty.Sdump(announcement),
pretty.Sdump(blockHeaderReq))
}
if err := sendConn.Write(&BlockHeaders{nextBlock.Header()}); err != nil {
return fmt.Errorf("failed to write to connection: %v", err)
}
}
// wait for block announcement // wait for block announcement
msg = recvConn.readAndServe(s.chain, timeout) msg = recvConn.readAndServe(s.chain, timeout)
switch msg := msg.(type) { switch msg := msg.(type) {
@ -762,6 +615,7 @@ func (s *Suite) hashAnnounce(isEth66 bool) error {
return fmt.Errorf("unexpected block hash announcement, wanted %v, got %v", nextBlock.Hash(), return fmt.Errorf("unexpected block hash announcement, wanted %v, got %v", nextBlock.Hash(),
hashes[0].Hash) hashes[0].Hash)
} }
case *NewBlock: case *NewBlock:
// node should only propagate NewBlock without having requested the body if the body is empty // node should only propagate NewBlock without having requested the body if the body is empty
nextBlockBody := nextBlock.Body() nextBlockBody := nextBlock.Body()
@ -780,7 +634,7 @@ func (s *Suite) hashAnnounce(isEth66 bool) error {
return fmt.Errorf("unexpected: %s", pretty.Sdump(msg)) return fmt.Errorf("unexpected: %s", pretty.Sdump(msg))
} }
// confirm node imported block // confirm node imported block
if err := s.waitForBlockImport(recvConn, nextBlock, isEth66); err != nil { if err := s.waitForBlockImport(recvConn, nextBlock); err != nil {
return fmt.Errorf("error waiting for node to import new block: %v", err) return fmt.Errorf("error waiting for node to import new block: %v", err)
} }
// update the chain // update the chain

View file

@ -350,7 +350,6 @@ func hexToCompact(hex []byte) []byte {
// TestSnapTrieNodes various forms of GetTrieNodes requests. // TestSnapTrieNodes various forms of GetTrieNodes requests.
func (s *Suite) TestSnapTrieNodes(t *utesting.T) { func (s *Suite) TestSnapTrieNodes(t *utesting.T) {
key := common.FromHex("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a") key := common.FromHex("0x00bf49f440a1cd0527e4d06e2765654c0f56452257516d793a9b8d604dcfdf2a")
// helper function to iterate the key, and generate the compact-encoded // helper function to iterate the key, and generate the compact-encoded
// trie paths along the way. // trie paths along the way.

View file

@ -21,32 +21,40 @@ import "github.com/ethereum/go-ethereum/eth/protocols/snap"
// GetAccountRange represents an account range query. // GetAccountRange represents an account range query.
type GetAccountRange snap.GetAccountRangePacket type GetAccountRange snap.GetAccountRangePacket
func (g GetAccountRange) Code() int { return 33 } func (msg GetAccountRange) Code() int { return 33 }
func (msg GetAccountRange) ReqID() uint64 { return msg.ID }
type AccountRange snap.AccountRangePacket type AccountRange snap.AccountRangePacket
func (g AccountRange) Code() int { return 34 } func (msg AccountRange) Code() int { return 34 }
func (msg AccountRange) ReqID() uint64 { return msg.ID }
type GetStorageRanges snap.GetStorageRangesPacket type GetStorageRanges snap.GetStorageRangesPacket
func (g GetStorageRanges) Code() int { return 35 } func (msg GetStorageRanges) Code() int { return 35 }
func (msg GetStorageRanges) ReqID() uint64 { return msg.ID }
type StorageRanges snap.StorageRangesPacket type StorageRanges snap.StorageRangesPacket
func (g StorageRanges) Code() int { return 36 } func (msg StorageRanges) Code() int { return 36 }
func (msg StorageRanges) ReqID() uint64 { return msg.ID }
type GetByteCodes snap.GetByteCodesPacket type GetByteCodes snap.GetByteCodesPacket
func (g GetByteCodes) Code() int { return 37 } func (msg GetByteCodes) Code() int { return 37 }
func (msg GetByteCodes) ReqID() uint64 { return msg.ID }
type ByteCodes snap.ByteCodesPacket type ByteCodes snap.ByteCodesPacket
func (g ByteCodes) Code() int { return 38 } func (msg ByteCodes) Code() int { return 38 }
func (msg ByteCodes) ReqID() uint64 { return msg.ID }
type GetTrieNodes snap.GetTrieNodesPacket type GetTrieNodes snap.GetTrieNodesPacket
func (g GetTrieNodes) Code() int { return 39 } func (msg GetTrieNodes) Code() int { return 39 }
func (msg GetTrieNodes) ReqID() uint64 { return msg.ID }
type TrieNodes snap.TrieNodesPacket type TrieNodes snap.TrieNodesPacket
func (g TrieNodes) Code() int { return 40 } func (msg TrieNodes) Code() int { return 40 }
func (msg TrieNodes) ReqID() uint64 { return msg.ID }

View file

@ -49,79 +49,30 @@ func NewSuite(dest *enode.Node, chainfile string, genesisfile string) (*Suite, e
}, nil }, nil
} }
func (s *Suite) AllEthTests() []utesting.Test {
return []utesting.Test{
// status
{Name: "TestStatus65", Fn: s.TestStatus65},
{Name: "TestStatus66", Fn: s.TestStatus66},
// get block headers
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65},
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66},
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66},
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66},
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66},
// get block bodies
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65},
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66},
// broadcast
{Name: "TestBroadcast65", Fn: s.TestBroadcast65},
{Name: "TestBroadcast66", Fn: s.TestBroadcast66},
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65},
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66},
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65},
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66},
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65},
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66},
// malicious handshakes + status
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65},
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65},
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66},
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66},
// test transactions
{Name: "TestTransaction65", Fn: s.TestTransaction65},
{Name: "TestTransaction66", Fn: s.TestTransaction66},
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65},
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66},
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66},
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66},
}
}
func (s *Suite) EthTests() []utesting.Test { func (s *Suite) EthTests() []utesting.Test {
return []utesting.Test{ return []utesting.Test{
{Name: "TestStatus65", Fn: s.TestStatus65}, // status
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65}, {Name: "TestStatus", Fn: s.TestStatus},
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65}, // get block headers
{Name: "TestBroadcast65", Fn: s.TestBroadcast65}, {Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders},
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65}, {Name: "TestSimultaneousRequests", Fn: s.TestSimultaneousRequests},
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65}, {Name: "TestSameRequestID", Fn: s.TestSameRequestID},
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65}, {Name: "TestZeroRequestID", Fn: s.TestZeroRequestID},
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65}, // get block bodies
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65}, {Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
{Name: "TestTransaction65", Fn: s.TestTransaction65}, // broadcast
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65}, {Name: "TestBroadcast", Fn: s.TestBroadcast},
} {Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
} {Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
{Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
func (s *Suite) Eth66Tests() []utesting.Test { // malicious handshakes + status
return []utesting.Test{ {Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
// only proceed with eth66 test suite if node supports eth 66 protocol {Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
{Name: "TestStatus66", Fn: s.TestStatus66}, // test transactions
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66}, {Name: "TestTransaction", Fn: s.TestTransaction},
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66}, {Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66}, {Name: "TestLargeTxRequest", Fn: s.TestLargeTxRequest},
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66}, {Name: "TestNewPooledTxs", Fn: s.TestNewPooledTxs},
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66},
{Name: "TestBroadcast66", Fn: s.TestBroadcast66},
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66},
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66},
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66},
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66},
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66},
{Name: "TestTransaction66", Fn: s.TestTransaction66},
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66},
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66},
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66},
} }
} }
@ -135,14 +86,9 @@ func (s *Suite) SnapTests() []utesting.Test {
} }
} }
var ( // TestStatus attempts to connect to the given node and exchange
eth66 = true // indicates whether suite should negotiate eth66 connection // a status message with it on the eth protocol.
eth65 = false // indicates whether suite should negotiate eth65 connection or below. func (s *Suite) TestStatus(t *utesting.T) {
)
// TestStatus65 attempts to connect to the given node and exchange
// a status message with it.
func (s *Suite) TestStatus65(t *utesting.T) {
conn, err := s.dial() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
@ -153,79 +99,32 @@ func (s *Suite) TestStatus65(t *utesting.T) {
} }
} }
// TestStatus66 attempts to connect to the given node and exchange // TestGetBlockHeaders tests whether the given node can respond to
// a status message with it on the eth66 protocol. // an eth `GetBlockHeaders` request and that the response is accurate.
func (s *Suite) TestStatus66(t *utesting.T) { func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
conn, err := s.dial66()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
}
// TestGetBlockHeaders65 tests whether the given node can respond to
// a `GetBlockHeaders` request accurately.
func (s *Suite) TestGetBlockHeaders65(t *utesting.T) {
conn, err := s.dial() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
defer conn.Close() defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("handshake(s) failed: %v", err)
}
// write request
req := &GetBlockHeaders{
Origin: eth.HashOrNumber{
Hash: s.chain.blocks[1].Hash(),
},
Amount: 2,
Skip: 1,
Reverse: false,
}
headers, err := conn.headersRequest(req, s.chain, eth65, 0)
if err != nil {
t.Fatalf("GetBlockHeaders request failed: %v", err)
}
// check for correct headers
expected, err := s.chain.GetHeaders(*req)
if err != nil {
t.Fatalf("failed to get headers for given request: %v", err)
}
if !headersMatch(expected, headers) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected, headers)
}
}
// TestGetBlockHeaders66 tests whether the given node can respond to
// an eth66 `GetBlockHeaders` request and that the response is accurate.
func (s *Suite) TestGetBlockHeaders66(t *utesting.T) {
conn, err := s.dial66()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err = conn.peer(s.chain, nil); err != nil { if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
// write request // write request
req := &GetBlockHeaders{ req := &GetBlockHeaders{
Origin: eth.HashOrNumber{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Hash: s.chain.blocks[1].Hash(), Origin: eth.HashOrNumber{Hash: s.chain.blocks[1].Hash()},
},
Amount: 2, Amount: 2,
Skip: 1, Skip: 1,
Reverse: false, Reverse: false,
},
} }
headers, err := conn.headersRequest(req, s.chain, eth66, 33) headers, err := conn.headersRequest(req, s.chain, 33)
if err != nil { if err != nil {
t.Fatalf("could not get block headers: %v", err) t.Fatalf("could not get block headers: %v", err)
} }
// check for correct headers // check for correct headers
expected, err := s.chain.GetHeaders(*req) expected, err := s.chain.GetHeaders(req)
if err != nil { if err != nil {
t.Fatalf("failed to get headers for given request: %v", err) t.Fatalf("failed to get headers for given request: %v", err)
} }
@ -234,12 +133,12 @@ func (s *Suite) TestGetBlockHeaders66(t *utesting.T) {
} }
} }
// TestSimultaneousRequests66 sends two simultaneous `GetBlockHeader` requests from // TestSimultaneousRequests sends two simultaneous `GetBlockHeader` requests from
// the same connection with different request IDs and checks to make sure the node // the same connection with different request IDs and checks to make sure the node
// responds with the correct headers per request. // responds with the correct headers per request.
func (s *Suite) TestSimultaneousRequests66(t *utesting.T) { func (s *Suite) TestSimultaneousRequests(t *utesting.T) {
// create a connection // create a connection
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
@ -247,8 +146,9 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) {
if err := conn.peer(s.chain, nil); err != nil { if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
// create two requests // create two requests
req1 := &eth.GetBlockHeadersPacket66{ req1 := &GetBlockHeaders{
RequestId: uint64(111), RequestId: uint64(111),
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{ Origin: eth.HashOrNumber{
@ -259,7 +159,7 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) {
Reverse: false, Reverse: false,
}, },
} }
req2 := &eth.GetBlockHeadersPacket66{ req2 := &GetBlockHeaders{
RequestId: uint64(222), RequestId: uint64(222),
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{ Origin: eth.HashOrNumber{
@ -270,46 +170,49 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) {
Reverse: false, Reverse: false,
}, },
} }
// write the first request // write the first request
if err := conn.Write66(req1, GetBlockHeaders{}.Code()); err != nil { if err := conn.Write(req1); err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }
// write the second request // write the second request
if err := conn.Write66(req2, GetBlockHeaders{}.Code()); err != nil { if err := conn.Write(req2); err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }
// wait for responses // wait for responses
msg := conn.waitForResponse(s.chain, timeout, req1.RequestId) msg := conn.waitForResponse(s.chain, timeout, req1.RequestId)
headers1, ok := msg.(BlockHeaders) headers1, ok := msg.(*BlockHeaders)
if !ok { if !ok {
t.Fatalf("unexpected %s", pretty.Sdump(msg)) t.Fatalf("unexpected %s", pretty.Sdump(msg))
} }
msg = conn.waitForResponse(s.chain, timeout, req2.RequestId) msg = conn.waitForResponse(s.chain, timeout, req2.RequestId)
headers2, ok := msg.(BlockHeaders) headers2, ok := msg.(*BlockHeaders)
if !ok { if !ok {
t.Fatalf("unexpected %s", pretty.Sdump(msg)) t.Fatalf("unexpected %s", pretty.Sdump(msg))
} }
// check received headers for accuracy // check received headers for accuracy
expected1, err := s.chain.GetHeaders(GetBlockHeaders(*req1.GetBlockHeadersPacket)) expected1, err := s.chain.GetHeaders(req1)
if err != nil { if err != nil {
t.Fatalf("failed to get expected headers for request 1: %v", err) t.Fatalf("failed to get expected headers for request 1: %v", err)
} }
expected2, err := s.chain.GetHeaders(GetBlockHeaders(*req2.GetBlockHeadersPacket)) expected2, err := s.chain.GetHeaders(req2)
if err != nil { if err != nil {
t.Fatalf("failed to get expected headers for request 2: %v", err) t.Fatalf("failed to get expected headers for request 2: %v", err)
} }
if !headersMatch(expected1, headers1) { if !headersMatch(expected1, headers1.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
} }
if !headersMatch(expected2, headers2) { if !headersMatch(expected2, headers2.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
} }
} }
// TestSameRequestID66 sends two requests with the same request ID to a // TestSameRequestID sends two requests with the same request ID to a
// single node. // single node.
func (s *Suite) TestSameRequestID66(t *utesting.T) { func (s *Suite) TestSameRequestID(t *utesting.T) {
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
@ -319,7 +222,7 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) {
} }
// create requests // create requests
reqID := uint64(1234) reqID := uint64(1234)
request1 := &eth.GetBlockHeadersPacket66{ request1 := &GetBlockHeaders{
RequestId: reqID, RequestId: reqID,
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{ Origin: eth.HashOrNumber{
@ -328,7 +231,7 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) {
Amount: 2, Amount: 2,
}, },
} }
request2 := &eth.GetBlockHeadersPacket66{ request2 := &GetBlockHeaders{
RequestId: reqID, RequestId: reqID,
GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Origin: eth.HashOrNumber{ Origin: eth.HashOrNumber{
@ -337,45 +240,48 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) {
Amount: 2, Amount: 2,
}, },
} }
// write the requests // write the requests
if err = conn.Write66(request1, GetBlockHeaders{}.Code()); err != nil { if err = conn.Write(request1); err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }
if err = conn.Write66(request2, GetBlockHeaders{}.Code()); err != nil { if err = conn.Write(request2); err != nil {
t.Fatalf("failed to write to connection: %v", err) t.Fatalf("failed to write to connection: %v", err)
} }
// wait for responses // wait for responses
msg := conn.waitForResponse(s.chain, timeout, reqID) msg := conn.waitForResponse(s.chain, timeout, reqID)
headers1, ok := msg.(BlockHeaders) headers1, ok := msg.(*BlockHeaders)
if !ok { if !ok {
t.Fatalf("unexpected %s", pretty.Sdump(msg)) t.Fatalf("unexpected %s", pretty.Sdump(msg))
} }
msg = conn.waitForResponse(s.chain, timeout, reqID) msg = conn.waitForResponse(s.chain, timeout, reqID)
headers2, ok := msg.(BlockHeaders) headers2, ok := msg.(*BlockHeaders)
if !ok { if !ok {
t.Fatalf("unexpected %s", pretty.Sdump(msg)) t.Fatalf("unexpected %s", pretty.Sdump(msg))
} }
// check if headers match // check if headers match
expected1, err := s.chain.GetHeaders(GetBlockHeaders(*request1.GetBlockHeadersPacket)) expected1, err := s.chain.GetHeaders(request1)
if err != nil { if err != nil {
t.Fatalf("failed to get expected block headers: %v", err) t.Fatalf("failed to get expected block headers: %v", err)
} }
expected2, err := s.chain.GetHeaders(GetBlockHeaders(*request2.GetBlockHeadersPacket)) expected2, err := s.chain.GetHeaders(request2)
if err != nil { if err != nil {
t.Fatalf("failed to get expected block headers: %v", err) t.Fatalf("failed to get expected block headers: %v", err)
} }
if !headersMatch(expected1, headers1) { if !headersMatch(expected1, headers1.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected1, headers1)
} }
if !headersMatch(expected2, headers2) { if !headersMatch(expected2, headers2.BlockHeadersPacket) {
t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2) t.Fatalf("header mismatch: \nexpected %v \ngot %v", expected2, headers2)
} }
} }
// TestZeroRequestID_66 checks that a message with a request ID of zero is still handled // TestZeroRequestID checks that a message with a request ID of zero is still handled
// by the node. // by the node.
func (s *Suite) TestZeroRequestID66(t *utesting.T) { func (s *Suite) TestZeroRequestID(t *utesting.T) {
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
@ -384,16 +290,16 @@ func (s *Suite) TestZeroRequestID66(t *utesting.T) {
t.Fatalf("peering failed: %v", err) t.Fatalf("peering failed: %v", err)
} }
req := &GetBlockHeaders{ req := &GetBlockHeaders{
Origin: eth.HashOrNumber{ GetBlockHeadersPacket: &eth.GetBlockHeadersPacket{
Number: 0, Origin: eth.HashOrNumber{Number: 0},
},
Amount: 2, Amount: 2,
},
} }
headers, err := conn.headersRequest(req, s.chain, eth66, 0) headers, err := conn.headersRequest(req, s.chain, 0)
if err != nil { if err != nil {
t.Fatalf("failed to get block headers: %v", err) t.Fatalf("failed to get block headers: %v", err)
} }
expected, err := s.chain.GetHeaders(*req) expected, err := s.chain.GetHeaders(req)
if err != nil { if err != nil {
t.Fatalf("failed to get expected block headers: %v", err) t.Fatalf("failed to get expected block headers: %v", err)
} }
@ -402,9 +308,9 @@ func (s *Suite) TestZeroRequestID66(t *utesting.T) {
} }
} }
// TestGetBlockBodies65 tests whether the given node can respond to // TestGetBlockBodies tests whether the given node can respond to
// a `GetBlockBodies` request and that the response is accurate. // a `GetBlockBodies` request and that the response is accurate.
func (s *Suite) TestGetBlockBodies65(t *utesting.T) { func (s *Suite) TestGetBlockBodies(t *utesting.T) {
conn, err := s.dial() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
@ -415,126 +321,39 @@ func (s *Suite) TestGetBlockBodies65(t *utesting.T) {
} }
// create block bodies request // create block bodies request
req := &GetBlockBodies{ req := &GetBlockBodies{
s.chain.blocks[54].Hash(),
s.chain.blocks[75].Hash(),
}
if err := conn.Write(req); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
// wait for response
switch msg := conn.readAndServe(s.chain, timeout).(type) {
case *BlockBodies:
t.Logf("received %d block bodies", len(*msg))
if len(*msg) != len(*req) {
t.Fatalf("wrong bodies in response: expected %d bodies, "+
"got %d", len(*req), len(*msg))
}
default:
t.Fatalf("unexpected: %s", pretty.Sdump(msg))
}
}
// TestGetBlockBodies66 tests whether the given node can respond to
// a `GetBlockBodies` request and that the response is accurate over
// the eth66 protocol.
func (s *Suite) TestGetBlockBodies66(t *utesting.T) {
conn, err := s.dial66()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
// create block bodies request
req := &eth.GetBlockBodiesPacket66{
RequestId: uint64(55), RequestId: uint64(55),
GetBlockBodiesPacket: eth.GetBlockBodiesPacket{ GetBlockBodiesPacket: eth.GetBlockBodiesPacket{
s.chain.blocks[54].Hash(), s.chain.blocks[54].Hash(),
s.chain.blocks[75].Hash(), s.chain.blocks[75].Hash(),
}, },
} }
if err := conn.Write66(req, GetBlockBodies{}.Code()); err != nil { if err := conn.Write(req); err != nil {
t.Fatalf("could not write to connection: %v", err) t.Fatalf("could not write to connection: %v", err)
} }
// wait for block bodies response // wait for block bodies response
msg := conn.waitForResponse(s.chain, timeout, req.RequestId) msg := conn.waitForResponse(s.chain, timeout, req.RequestId)
blockBodies, ok := msg.(BlockBodies) resp, ok := msg.(*BlockBodies)
if !ok { if !ok {
t.Fatalf("unexpected: %s", pretty.Sdump(msg)) t.Fatalf("unexpected: %s", pretty.Sdump(msg))
} }
t.Logf("received %d block bodies", len(blockBodies)) bodies := resp.BlockBodiesPacket
if len(blockBodies) != len(req.GetBlockBodiesPacket) { t.Logf("received %d block bodies", len(bodies))
if len(bodies) != len(req.GetBlockBodiesPacket) {
t.Fatalf("wrong bodies in response: expected %d bodies, "+ t.Fatalf("wrong bodies in response: expected %d bodies, "+
"got %d", len(req.GetBlockBodiesPacket), len(blockBodies)) "got %d", len(req.GetBlockBodiesPacket), len(bodies))
} }
} }
// TestBroadcast65 tests whether a block announcement is correctly // TestBroadcast tests whether a block announcement is correctly
// propagated to the given node's peer(s). // propagated to the node's peers.
func (s *Suite) TestBroadcast65(t *utesting.T) { func (s *Suite) TestBroadcast(t *utesting.T) {
if err := s.sendNextBlock(eth65); err != nil { if err := s.sendNextBlock(); err != nil {
t.Fatalf("block broadcast failed: %v", err) t.Fatalf("block broadcast failed: %v", err)
} }
} }
// TestBroadcast66 tests whether a block announcement is correctly // TestLargeAnnounce tests the announcement mechanism with a large block.
// propagated to the given node's peer(s) on the eth66 protocol. func (s *Suite) TestLargeAnnounce(t *utesting.T) {
func (s *Suite) TestBroadcast66(t *utesting.T) {
if err := s.sendNextBlock(eth66); err != nil {
t.Fatalf("block broadcast failed: %v", err)
}
}
// TestLargeAnnounce65 tests the announcement mechanism with a large block.
func (s *Suite) TestLargeAnnounce65(t *utesting.T) {
nextBlock := len(s.chain.blocks)
blocks := []*NewBlock{
{
Block: largeBlock(),
TD: s.fullChain.TotalDifficultyAt(nextBlock),
},
{
Block: s.fullChain.blocks[nextBlock],
TD: largeNumber(2),
},
{
Block: largeBlock(),
TD: largeNumber(2),
},
}
for i, blockAnnouncement := range blocks {
t.Logf("Testing malicious announcement: %v\n", i)
conn, err := s.dial()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
if err = conn.peer(s.chain, nil); err != nil {
t.Fatalf("peering failed: %v", err)
}
if err = conn.Write(blockAnnouncement); err != nil {
t.Fatalf("could not write to connection: %v", err)
}
// Invalid announcement, check that peer disconnected
switch msg := conn.readAndServe(s.chain, time.Second*8).(type) {
case *Disconnect:
case *Error:
break
default:
t.Fatalf("unexpected: %s wanted disconnect", pretty.Sdump(msg))
}
conn.Close()
}
// Test the last block as a valid block
if err := s.sendNextBlock(eth65); err != nil {
t.Fatalf("failed to broadcast next block: %v", err)
}
}
// TestLargeAnnounce66 tests the announcement mechanism with a large
// block over the eth66 protocol.
func (s *Suite) TestLargeAnnounce66(t *utesting.T) {
nextBlock := len(s.chain.blocks) nextBlock := len(s.chain.blocks)
blocks := []*NewBlock{ blocks := []*NewBlock{
{ {
@ -553,7 +372,7 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) {
for i, blockAnnouncement := range blocks[0:3] { for i, blockAnnouncement := range blocks[0:3] {
t.Logf("Testing malicious announcement: %v\n", i) t.Logf("Testing malicious announcement: %v\n", i)
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
@ -564,7 +383,7 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) {
t.Fatalf("could not write to connection: %v", err) t.Fatalf("could not write to connection: %v", err)
} }
// Invalid announcement, check that peer disconnected // Invalid announcement, check that peer disconnected
switch msg := conn.readAndServe(s.chain, time.Second*8).(type) { switch msg := conn.readAndServe(s.chain, 8*time.Second).(type) {
case *Disconnect: case *Disconnect:
case *Error: case *Error:
break break
@ -574,58 +393,35 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) {
conn.Close() conn.Close()
} }
// Test the last block as a valid block // Test the last block as a valid block
if err := s.sendNextBlock(eth66); err != nil { if err := s.sendNextBlock(); err != nil {
t.Fatalf("failed to broadcast next block: %v", err) t.Fatalf("failed to broadcast next block: %v", err)
} }
} }
// TestOldAnnounce65 tests the announcement mechanism with an old block. // TestOldAnnounce tests the announcement mechanism with an old block.
func (s *Suite) TestOldAnnounce65(t *utesting.T) { func (s *Suite) TestOldAnnounce(t *utesting.T) {
if err := s.oldAnnounce(eth65); err != nil { if err := s.oldAnnounce(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
// TestOldAnnounce66 tests the announcement mechanism with an old block, // TestBlockHashAnnounce sends a new block hash announcement and expects
// over the eth66 protocol.
func (s *Suite) TestOldAnnounce66(t *utesting.T) {
if err := s.oldAnnounce(eth66); err != nil {
t.Fatal(err)
}
}
// TestBlockHashAnnounce65 sends a new block hash announcement and expects
// the node to perform a `GetBlockHeaders` request. // the node to perform a `GetBlockHeaders` request.
func (s *Suite) TestBlockHashAnnounce65(t *utesting.T) { func (s *Suite) TestBlockHashAnnounce(t *utesting.T) {
if err := s.hashAnnounce(eth65); err != nil { if err := s.hashAnnounce(); err != nil {
t.Fatalf("block hash announcement failed: %v", err) t.Fatalf("block hash announcement failed: %v", err)
} }
} }
// TestBlockHashAnnounce66 sends a new block hash announcement and expects // TestMaliciousHandshake tries to send malicious data during the handshake.
// the node to perform a `GetBlockHeaders` request. func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
func (s *Suite) TestBlockHashAnnounce66(t *utesting.T) { if err := s.maliciousHandshakes(t); err != nil {
if err := s.hashAnnounce(eth66); err != nil {
t.Fatalf("block hash announcement failed: %v", err)
}
}
// TestMaliciousHandshake65 tries to send malicious data during the handshake.
func (s *Suite) TestMaliciousHandshake65(t *utesting.T) {
if err := s.maliciousHandshakes(t, eth65); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
// TestMaliciousHandshake66 tries to send malicious data during the handshake. // TestMaliciousStatus sends a status package with a large total difficulty.
func (s *Suite) TestMaliciousHandshake66(t *utesting.T) { func (s *Suite) TestMaliciousStatus(t *utesting.T) {
if err := s.maliciousHandshakes(t, eth66); err != nil {
t.Fatal(err)
}
}
// TestMaliciousStatus65 sends a status package with a large total difficulty.
func (s *Suite) TestMaliciousStatus65(t *utesting.T) {
conn, err := s.dial() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
@ -637,58 +433,28 @@ func (s *Suite) TestMaliciousStatus65(t *utesting.T) {
} }
} }
// TestMaliciousStatus66 sends a status package with a large total // TestTransaction sends a valid transaction to the node and
// difficulty over the eth66 protocol.
func (s *Suite) TestMaliciousStatus66(t *utesting.T) {
conn, err := s.dial66()
if err != nil {
t.Fatalf("dial failed: %v", err)
}
defer conn.Close()
if err := s.maliciousStatus(conn); err != nil {
t.Fatal(err)
}
}
// TestTransaction65 sends a valid transaction to the node and
// checks if the transaction gets propagated. // checks if the transaction gets propagated.
func (s *Suite) TestTransaction65(t *utesting.T) { func (s *Suite) TestTransaction(t *utesting.T) {
if err := s.sendSuccessfulTxs(t, eth65); err != nil { if err := s.sendSuccessfulTxs(t); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
// TestTransaction66 sends a valid transaction to the node and // TestMaliciousTx sends several invalid transactions and tests whether
// checks if the transaction gets propagated.
func (s *Suite) TestTransaction66(t *utesting.T) {
if err := s.sendSuccessfulTxs(t, eth66); err != nil {
t.Fatal(err)
}
}
// TestMaliciousTx65 sends several invalid transactions and tests whether
// the node will propagate them. // the node will propagate them.
func (s *Suite) TestMaliciousTx65(t *utesting.T) { func (s *Suite) TestMaliciousTx(t *utesting.T) {
if err := s.sendMaliciousTxs(t, eth65); err != nil { if err := s.sendMaliciousTxs(t); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
// TestMaliciousTx66 sends several invalid transactions and tests whether // TestLargeTxRequest tests whether a node can fulfill a large GetPooledTransactions
// the node will propagate them.
func (s *Suite) TestMaliciousTx66(t *utesting.T) {
if err := s.sendMaliciousTxs(t, eth66); err != nil {
t.Fatal(err)
}
}
// TestLargeTxRequest66 tests whether a node can fulfill a large GetPooledTransactions
// request. // request.
func (s *Suite) TestLargeTxRequest66(t *utesting.T) { func (s *Suite) TestLargeTxRequest(t *utesting.T) {
// send the next block to ensure the node is no longer syncing and // send the next block to ensure the node is no longer syncing and
// is able to accept txs // is able to accept txs
if err := s.sendNextBlock(eth66); err != nil { if err := s.sendNextBlock(); err != nil {
t.Fatalf("failed to send next block: %v", err) t.Fatalf("failed to send next block: %v", err)
} }
// send 2000 transactions to the node // send 2000 transactions to the node
@ -701,7 +467,7 @@ func (s *Suite) TestLargeTxRequest66(t *utesting.T) {
} }
// set up connection to receive to ensure node is peered with the receiving connection // set up connection to receive to ensure node is peered with the receiving connection
// before tx request is sent // before tx request is sent
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
@ -714,17 +480,17 @@ func (s *Suite) TestLargeTxRequest66(t *utesting.T) {
for _, hash := range hashMap { for _, hash := range hashMap {
hashes = append(hashes, hash) hashes = append(hashes, hash)
} }
getTxReq := &eth.GetPooledTransactionsPacket66{ getTxReq := &GetPooledTransactions{
RequestId: 1234, RequestId: 1234,
GetPooledTransactionsPacket: hashes, GetPooledTransactionsPacket: hashes,
} }
if err = conn.Write66(getTxReq, GetPooledTransactions{}.Code()); err != nil { if err = conn.Write(getTxReq); err != nil {
t.Fatalf("could not write to conn: %v", err) t.Fatalf("could not write to conn: %v", err)
} }
// check that all received transactions match those that were sent to node // check that all received transactions match those that were sent to node
switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) { switch msg := conn.waitForResponse(s.chain, timeout, getTxReq.RequestId).(type) {
case PooledTransactions: case *PooledTransactions:
for _, gotTx := range msg { for _, gotTx := range msg.PooledTransactionsPacket {
if _, exists := hashMap[gotTx.Hash()]; !exists { if _, exists := hashMap[gotTx.Hash()]; !exists {
t.Fatalf("unexpected tx received: %v", gotTx.Hash()) t.Fatalf("unexpected tx received: %v", gotTx.Hash())
} }
@ -734,12 +500,12 @@ func (s *Suite) TestLargeTxRequest66(t *utesting.T) {
} }
} }
// TestNewPooledTxs_66 tests whether a node will do a GetPooledTransactions // TestNewPooledTxs tests whether a node will do a GetPooledTransactions
// request upon receiving a NewPooledTransactionHashes announcement. // request upon receiving a NewPooledTransactionHashes announcement.
func (s *Suite) TestNewPooledTxs66(t *utesting.T) { func (s *Suite) TestNewPooledTxs(t *utesting.T) {
// send the next block to ensure the node is no longer syncing and // send the next block to ensure the node is no longer syncing and
// is able to accept txs // is able to accept txs
if err := s.sendNextBlock(eth66); err != nil { if err := s.sendNextBlock(); err != nil {
t.Fatalf("failed to send next block: %v", err) t.Fatalf("failed to send next block: %v", err)
} }
@ -757,7 +523,7 @@ func (s *Suite) TestNewPooledTxs66(t *utesting.T) {
announce := NewPooledTransactionHashes(hashes) announce := NewPooledTransactionHashes(hashes)
// send announcement // send announcement
conn, err := s.dial66() conn, err := s.dial()
if err != nil { if err != nil {
t.Fatalf("dial failed: %v", err) t.Fatalf("dial failed: %v", err)
} }
@ -771,11 +537,11 @@ func (s *Suite) TestNewPooledTxs66(t *utesting.T) {
// wait for GetPooledTxs request // wait for GetPooledTxs request
for { for {
_, msg := conn.readAndServe66(s.chain, timeout) msg := conn.readAndServe(s.chain, timeout)
switch msg := msg.(type) { switch msg := msg.(type) {
case GetPooledTransactions: case *GetPooledTransactions:
if len(msg) != len(hashes) { if len(msg.GetPooledTransactionsPacket) != len(hashes) {
t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg)) t.Fatalf("unexpected number of txs requested: wanted %d, got %d", len(hashes), len(msg.GetPooledTransactionsPacket))
} }
return return
// ignore propagated txs from previous tests // ignore propagated txs from previous tests

View file

@ -45,7 +45,7 @@ func TestEthSuite(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("could not create new test suite: %v", err) t.Fatalf("could not create new test suite: %v", err)
} }
for _, test := range suite.Eth66Tests() { for _, test := range suite.EthTests() {
t.Run(test.Name, func(t *testing.T) { t.Run(test.Name, func(t *testing.T) {
result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout) result := utesting.RunTAP([]utesting.Test{{Name: test.Name, Fn: test.Fn}}, os.Stdout)
if result[0].Failed { if result[0].Failed {

View file

@ -32,7 +32,7 @@ import (
//var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7") //var faucetAddr = common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7")
var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") var faucetKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
func (s *Suite) sendSuccessfulTxs(t *utesting.T, isEth66 bool) error { func (s *Suite) sendSuccessfulTxs(t *utesting.T) error {
tests := []*types.Transaction{ tests := []*types.Transaction{
getNextTxFromChain(s), getNextTxFromChain(s),
unknownTx(s), unknownTx(s),
@ -48,15 +48,15 @@ func (s *Suite) sendSuccessfulTxs(t *utesting.T, isEth66 bool) error {
prevTx = tests[i-1] prevTx = tests[i-1]
} }
// write tx to connection // write tx to connection
if err := sendSuccessfulTx(s, tx, prevTx, isEth66); err != nil { if err := sendSuccessfulTx(s, tx, prevTx); err != nil {
return fmt.Errorf("send successful tx test failed: %v", err) return fmt.Errorf("send successful tx test failed: %v", err)
} }
} }
return nil return nil
} }
func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction, isEth66 bool) error { func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction) error {
sendConn, recvConn, err := s.createSendAndRecvConns(isEth66) sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil { if err != nil {
return err return err
} }
@ -73,8 +73,10 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
if err = recvConn.peer(s.chain, nil); err != nil { if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err) return fmt.Errorf("peering failed: %v", err)
} }
// update last nonce seen // update last nonce seen
nonce = tx.Nonce() nonce = tx.Nonce()
// Wait for the transaction announcement // Wait for the transaction announcement
for { for {
switch msg := recvConn.readAndServe(s.chain, timeout).(type) { switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
@ -114,7 +116,7 @@ func sendSuccessfulTx(s *Suite, tx *types.Transaction, prevTx *types.Transaction
} }
} }
func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error { func (s *Suite) sendMaliciousTxs(t *utesting.T) error {
badTxs := []*types.Transaction{ badTxs := []*types.Transaction{
getOldTxFromChain(s), getOldTxFromChain(s),
invalidNonceTx(s), invalidNonceTx(s),
@ -122,16 +124,9 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
hugeGasPrice(s), hugeGasPrice(s),
hugeData(s), hugeData(s),
} }
// setup receiving connection before sending malicious txs // setup receiving connection before sending malicious txs
var ( recvConn, err := s.dial()
recvConn *Conn
err error
)
if isEth66 {
recvConn, err = s.dial66()
} else {
recvConn, err = s.dial()
}
if err != nil { if err != nil {
return fmt.Errorf("dial failed: %v", err) return fmt.Errorf("dial failed: %v", err)
} }
@ -139,9 +134,10 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
if err = recvConn.peer(s.chain, nil); err != nil { if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err) return fmt.Errorf("peering failed: %v", err)
} }
for i, tx := range badTxs { for i, tx := range badTxs {
t.Logf("Testing malicious tx propagation: %v\n", i) t.Logf("Testing malicious tx propagation: %v\n", i)
if err = sendMaliciousTx(s, tx, isEth66); err != nil { if err = sendMaliciousTx(s, tx); err != nil {
return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err) return fmt.Errorf("malicious tx test failed:\ntx: %v\nerror: %v", tx, err)
} }
} }
@ -149,17 +145,8 @@ func (s *Suite) sendMaliciousTxs(t *utesting.T, isEth66 bool) error {
return checkMaliciousTxPropagation(s, badTxs, recvConn) return checkMaliciousTxPropagation(s, badTxs, recvConn)
} }
func sendMaliciousTx(s *Suite, tx *types.Transaction, isEth66 bool) error { func sendMaliciousTx(s *Suite, tx *types.Transaction) error {
// setup connection conn, err := s.dial()
var (
conn *Conn
err error
)
if isEth66 {
conn, err = s.dial66()
} else {
conn, err = s.dial()
}
if err != nil { if err != nil {
return fmt.Errorf("dial failed: %v", err) return fmt.Errorf("dial failed: %v", err)
} }
@ -167,6 +154,7 @@ func sendMaliciousTx(s *Suite, tx *types.Transaction, isEth66 bool) error {
if err = conn.peer(s.chain, nil); err != nil { if err = conn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err) return fmt.Errorf("peering failed: %v", err)
} }
// write malicious tx // write malicious tx
if err = conn.Write(&Transactions{tx}); err != nil { if err = conn.Write(&Transactions{tx}); err != nil {
return fmt.Errorf("failed to write to connection: %v", err) return fmt.Errorf("failed to write to connection: %v", err)
@ -182,7 +170,7 @@ func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction
txMsg := Transactions(txs) txMsg := Transactions(txs)
t.Logf("sending %d txs\n", len(txs)) t.Logf("sending %d txs\n", len(txs))
sendConn, recvConn, err := s.createSendAndRecvConns(true) sendConn, recvConn, err := s.createSendAndRecvConns()
if err != nil { if err != nil {
return err return err
} }
@ -194,15 +182,19 @@ func sendMultipleSuccessfulTxs(t *utesting.T, s *Suite, txs []*types.Transaction
if err = recvConn.peer(s.chain, nil); err != nil { if err = recvConn.peer(s.chain, nil); err != nil {
return fmt.Errorf("peering failed: %v", err) return fmt.Errorf("peering failed: %v", err)
} }
// Send the transactions // Send the transactions
if err = sendConn.Write(&txMsg); err != nil { if err = sendConn.Write(&txMsg); err != nil {
return fmt.Errorf("failed to write message to connection: %v", err) return fmt.Errorf("failed to write message to connection: %v", err)
} }
// update nonce // update nonce
nonce = txs[len(txs)-1].Nonce() nonce = txs[len(txs)-1].Nonce()
// Wait for the transaction announcement(s) and make sure all sent txs are being propagated
// Wait for the transaction announcement(s) and make sure all sent txs are being propagated.
// all txs should be announced within 3 announcements.
recvHashes := make([]common.Hash, 0) recvHashes := make([]common.Hash, 0)
// all txs should be announced within 3 announcements
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
switch msg := recvConn.readAndServe(s.chain, timeout).(type) { switch msg := recvConn.readAndServe(s.chain, timeout).(type) {
case *Transactions: case *Transactions:

View file

@ -29,6 +29,7 @@ import (
type Message interface { type Message interface {
Code() int Code() int
ReqID() uint64
} }
type Error struct { type Error struct {
@ -37,9 +38,11 @@ type Error struct {
func (e *Error) Unwrap() error { return e.err } func (e *Error) Unwrap() error { return e.err }
func (e *Error) Error() string { return e.err.Error() } func (e *Error) Error() string { return e.err.Error() }
func (e *Error) Code() int { return -1 }
func (e *Error) String() string { return e.Error() } func (e *Error) String() string { return e.Error() }
func (e *Error) Code() int { return -1 }
func (e *Error) ReqID() uint64 { return 0 }
func errorf(format string, args ...interface{}) *Error { func errorf(format string, args ...interface{}) *Error {
return &Error{fmt.Errorf(format, args...)} return &Error{fmt.Errorf(format, args...)}
} }
@ -56,73 +59,88 @@ type Hello struct {
Rest []rlp.RawValue `rlp:"tail"` Rest []rlp.RawValue `rlp:"tail"`
} }
func (h Hello) Code() int { return 0x00 } func (msg Hello) Code() int { return 0x00 }
func (msg Hello) ReqID() uint64 { return 0 }
// Disconnect is the RLP structure for a disconnect message. // Disconnect is the RLP structure for a disconnect message.
type Disconnect struct { type Disconnect struct {
Reason p2p.DiscReason Reason p2p.DiscReason
} }
func (d Disconnect) Code() int { return 0x01 } func (msg Disconnect) Code() int { return 0x01 }
func (msg Disconnect) ReqID() uint64 { return 0 }
type Ping struct{} type Ping struct{}
func (p Ping) Code() int { return 0x02 } func (msg Ping) Code() int { return 0x02 }
func (msg Ping) ReqID() uint64 { return 0 }
type Pong struct{} type Pong struct{}
func (p Pong) Code() int { return 0x03 } func (msg Pong) Code() int { return 0x03 }
func (msg Pong) ReqID() uint64 { return 0 }
// Status is the network packet for the status message for eth/64 and later. // Status is the network packet for the status message for eth/64 and later.
type Status eth.StatusPacket type Status eth.StatusPacket
func (s Status) Code() int { return 16 } func (msg Status) Code() int { return 16 }
func (msg Status) ReqID() uint64 { return 0 }
// NewBlockHashes is the network packet for the block announcements. // NewBlockHashes is the network packet for the block announcements.
type NewBlockHashes eth.NewBlockHashesPacket type NewBlockHashes eth.NewBlockHashesPacket
func (nbh NewBlockHashes) Code() int { return 17 } func (msg NewBlockHashes) Code() int { return 17 }
func (msg NewBlockHashes) ReqID() uint64 { return 0 }
type Transactions eth.TransactionsPacket type Transactions eth.TransactionsPacket
func (t Transactions) Code() int { return 18 } func (msg Transactions) Code() int { return 18 }
func (msg Transactions) ReqID() uint64 { return 18 }
// GetBlockHeaders represents a block header query. // GetBlockHeaders represents a block header query.
type GetBlockHeaders eth.GetBlockHeadersPacket type GetBlockHeaders eth.GetBlockHeadersPacket66
func (g GetBlockHeaders) Code() int { return 19 } func (msg GetBlockHeaders) Code() int { return 19 }
func (msg GetBlockHeaders) ReqID() uint64 { return msg.RequestId }
type BlockHeaders eth.BlockHeadersPacket type BlockHeaders eth.BlockHeadersPacket66
func (bh BlockHeaders) Code() int { return 20 } func (msg BlockHeaders) Code() int { return 20 }
func (msg BlockHeaders) ReqID() uint64 { return msg.RequestId }
// GetBlockBodies represents a GetBlockBodies request // GetBlockBodies represents a GetBlockBodies request
type GetBlockBodies eth.GetBlockBodiesPacket type GetBlockBodies eth.GetBlockBodiesPacket66
func (gbb GetBlockBodies) Code() int { return 21 } func (msg GetBlockBodies) Code() int { return 21 }
func (msg GetBlockBodies) ReqID() uint64 { return msg.RequestId }
// BlockBodies is the network packet for block content distribution. // BlockBodies is the network packet for block content distribution.
type BlockBodies eth.BlockBodiesPacket type BlockBodies eth.BlockBodiesPacket66
func (bb BlockBodies) Code() int { return 22 } func (msg BlockBodies) Code() int { return 22 }
func (msg BlockBodies) ReqID() uint64 { return msg.RequestId }
// NewBlock is the network packet for the block propagation message. // NewBlock is the network packet for the block propagation message.
type NewBlock eth.NewBlockPacket type NewBlock eth.NewBlockPacket
func (nb NewBlock) Code() int { return 23 } func (msg NewBlock) Code() int { return 23 }
func (msg NewBlock) ReqID() uint64 { return 0 }
// NewPooledTransactionHashes is the network packet for the tx hash propagation message. // NewPooledTransactionHashes is the network packet for the tx hash propagation message.
type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket type NewPooledTransactionHashes eth.NewPooledTransactionHashesPacket
func (nb NewPooledTransactionHashes) Code() int { return 24 } func (msg NewPooledTransactionHashes) Code() int { return 24 }
func (msg NewPooledTransactionHashes) ReqID() uint64 { return 0 }
type GetPooledTransactions eth.GetPooledTransactionsPacket type GetPooledTransactions eth.GetPooledTransactionsPacket66
func (gpt GetPooledTransactions) Code() int { return 25 } func (msg GetPooledTransactions) Code() int { return 25 }
func (msg GetPooledTransactions) ReqID() uint64 { return msg.RequestId }
type PooledTransactions eth.PooledTransactionsPacket type PooledTransactions eth.PooledTransactionsPacket66
func (pt PooledTransactions) Code() int { return 26 } func (msg PooledTransactions) Code() int { return 26 }
func (msg PooledTransactions) ReqID() uint64 { return msg.RequestId }
// Conn represents an individual connection with a peer // Conn represents an individual connection with a peer
type Conn struct { type Conn struct {
@ -135,62 +153,13 @@ type Conn struct {
caps []p2p.Cap caps []p2p.Cap
} }
// Read reads an eth packet from the connection. // Read reads an eth66 packet from the connection.
func (c *Conn) Read() Message { func (c *Conn) Read() Message {
code, rawData, _, err := c.Conn.Read() code, rawData, _, err := c.Conn.Read()
if err != nil { if err != nil {
return errorf("could not read from connection: %v", err) return errorf("could not read from connection: %v", err)
} }
var msg Message
switch int(code) {
case (Hello{}).Code():
msg = new(Hello)
case (Ping{}).Code():
msg = new(Ping)
case (Pong{}).Code():
msg = new(Pong)
case (Disconnect{}).Code():
msg = new(Disconnect)
case (Status{}).Code():
msg = new(Status)
case (GetBlockHeaders{}).Code():
msg = new(GetBlockHeaders)
case (BlockHeaders{}).Code():
msg = new(BlockHeaders)
case (GetBlockBodies{}).Code():
msg = new(GetBlockBodies)
case (BlockBodies{}).Code():
msg = new(BlockBodies)
case (NewBlock{}).Code():
msg = new(NewBlock)
case (NewBlockHashes{}).Code():
msg = new(NewBlockHashes)
case (Transactions{}).Code():
msg = new(Transactions)
case (NewPooledTransactionHashes{}).Code():
msg = new(NewPooledTransactionHashes)
case (GetPooledTransactions{}.Code()):
msg = new(GetPooledTransactions)
case (PooledTransactions{}.Code()):
msg = new(PooledTransactions)
default:
return errorf("invalid message code: %d", code)
}
// if message is devp2p, decode here
if err := rlp.DecodeBytes(rawData, msg); err != nil {
return errorf("could not rlp decode message: %v", err)
}
return msg
}
// Read66 reads an eth66 packet from the connection.
func (c *Conn) Read66() (uint64, Message) {
code, rawData, _, err := c.Conn.Read()
if err != nil {
return 0, errorf("could not read from connection: %v", err)
}
var msg Message var msg Message
switch int(code) { switch int(code) {
case (Hello{}).Code(): case (Hello{}).Code():
@ -206,27 +175,27 @@ func (c *Conn) Read66() (uint64, Message) {
case (GetBlockHeaders{}).Code(): case (GetBlockHeaders{}).Code():
ethMsg := new(eth.GetBlockHeadersPacket66) ethMsg := new(eth.GetBlockHeadersPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return ethMsg.RequestId, GetBlockHeaders(*ethMsg.GetBlockHeadersPacket) return (*GetBlockHeaders)(ethMsg)
case (BlockHeaders{}).Code(): case (BlockHeaders{}).Code():
ethMsg := new(eth.BlockHeadersPacket66) ethMsg := new(eth.BlockHeadersPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return ethMsg.RequestId, BlockHeaders(ethMsg.BlockHeadersPacket) return (*BlockHeaders)(ethMsg)
case (GetBlockBodies{}).Code(): case (GetBlockBodies{}).Code():
ethMsg := new(eth.GetBlockBodiesPacket66) ethMsg := new(eth.GetBlockBodiesPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return ethMsg.RequestId, GetBlockBodies(ethMsg.GetBlockBodiesPacket) return (*GetBlockBodies)(ethMsg)
case (BlockBodies{}).Code(): case (BlockBodies{}).Code():
ethMsg := new(eth.BlockBodiesPacket66) ethMsg := new(eth.BlockBodiesPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return ethMsg.RequestId, BlockBodies(ethMsg.BlockBodiesPacket) return (*BlockBodies)(ethMsg)
case (NewBlock{}).Code(): case (NewBlock{}).Code():
msg = new(NewBlock) msg = new(NewBlock)
case (NewBlockHashes{}).Code(): case (NewBlockHashes{}).Code():
@ -238,26 +207,26 @@ func (c *Conn) Read66() (uint64, Message) {
case (GetPooledTransactions{}.Code()): case (GetPooledTransactions{}.Code()):
ethMsg := new(eth.GetPooledTransactionsPacket66) ethMsg := new(eth.GetPooledTransactionsPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return ethMsg.RequestId, GetPooledTransactions(ethMsg.GetPooledTransactionsPacket) return (*GetPooledTransactions)(ethMsg)
case (PooledTransactions{}.Code()): case (PooledTransactions{}.Code()):
ethMsg := new(eth.PooledTransactionsPacket66) ethMsg := new(eth.PooledTransactionsPacket66)
if err := rlp.DecodeBytes(rawData, ethMsg); err != nil { if err := rlp.DecodeBytes(rawData, ethMsg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return ethMsg.RequestId, PooledTransactions(ethMsg.PooledTransactionsPacket) return (*PooledTransactions)(ethMsg)
default: default:
msg = errorf("invalid message code: %d", code) msg = errorf("invalid message code: %d", code)
} }
if msg != nil { if msg != nil {
if err := rlp.DecodeBytes(rawData, msg); err != nil { if err := rlp.DecodeBytes(rawData, msg); err != nil {
return 0, errorf("could not rlp decode message: %v", err) return errorf("could not rlp decode message: %v", err)
} }
return 0, msg return msg
} }
return 0, errorf("invalid message: %s", string(rawData)) return errorf("invalid message: %s", string(rawData))
} }
// Write writes a eth packet to the connection. // Write writes a eth packet to the connection.
@ -270,16 +239,6 @@ func (c *Conn) Write(msg Message) error {
return err return err
} }
// Write66 writes an eth66 packet to the connection.
func (c *Conn) Write66(req eth.Packet, code int) error {
payload, err := rlp.EncodeToBytes(req)
if err != nil {
return err
}
_, err = c.Conn.Write(uint64(code), payload)
return err
}
// ReadSnap reads a snap/1 response with the given id from the connection. // ReadSnap reads a snap/1 response with the given id from the connection.
func (c *Conn) ReadSnap(id uint64) (Message, error) { func (c *Conn) ReadSnap(id uint64) (Message, error) {
respId := id + 1 respId := id + 1
@ -315,7 +274,6 @@ func (c *Conn) ReadSnap(id uint64) (Message, error) {
return nil, fmt.Errorf("could not rlp decode message: %v", err) return nil, fmt.Errorf("could not rlp decode message: %v", err)
} }
return snpMsg.(Message), nil return snpMsg.(Message), nil
} }
return nil, fmt.Errorf("request timed out") return nil, fmt.Errorf("request timed out")
} }

View file

@ -181,7 +181,7 @@ func parseFilterLimit(args []string) (int, error) {
return limit, nil return limit, nil
} }
// andFilter parses node filters in args and and returns a single filter that requires all // andFilter parses node filters in args and returns a single filter that requires all
// of them to match. // of them to match.
func andFilter(args []string) (nodeFilter, error) { func andFilter(args []string) (nodeFilter, error) {
checks, err := parseFilters(args) checks, err := parseFilters(args)

View file

@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest" "github.com/ethereum/go-ethereum/cmd/devp2p/internal/ethtest"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/utesting"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/rlpx" "github.com/ethereum/go-ethereum/p2p/rlpx"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -110,13 +109,8 @@ func rlpxEthTest(ctx *cli.Context) error {
if err != nil { if err != nil {
exit(err) exit(err)
} }
// check if given node supports eth66, and if so, run eth66 protocol tests as well
is66Failed, _ := utesting.Run(utesting.Test{Name: "Is_66", Fn: suite.Is_66})
if is66Failed {
return runTests(ctx, suite.EthTests()) return runTests(ctx, suite.EthTests())
} }
return runTests(ctx, suite.AllEthTests())
}
// rlpxSnapTest runs the snap protocol test suite. // rlpxSnapTest runs the snap protocol test suite.
func rlpxSnapTest(ctx *cli.Context) error { func rlpxSnapTest(ctx *cli.Context) error {

View file

@ -100,7 +100,6 @@ type rejectedTx struct {
func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
txs types.Transactions, miningReward int64, txs types.Transactions, miningReward int64,
getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) { getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) {
// Capture errors for BLOCKHASH operation, if we haven't been supplied the // Capture errors for BLOCKHASH operation, if we haven't been supplied the
// required blockhashes // required blockhashes
var hashError error var hashError error
@ -269,7 +268,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
} }
func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB { func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB {
sdb := state.NewDatabase(db) sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true})
statedb, _ := state.New(common.Hash{}, sdb, nil) statedb, _ := state.New(common.Hash{}, sdb, nil)
for addr, a := range accounts { for addr, a := range accounts {
statedb.SetCode(addr, a.Code) statedb.SetCode(addr, a.Code)

View file

@ -138,7 +138,7 @@ func runCmd(ctx *cli.Context) error {
gen := readGenesis(ctx.String(GenesisFlag.Name)) gen := readGenesis(ctx.String(GenesisFlag.Name))
genesisConfig = gen genesisConfig = gen
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := gen.ToBlock(db) genesis := gen.MustCommit(db)
statedb, _ = state.New(genesis.Root(), state.NewDatabase(db), nil) statedb, _ = state.New(genesis.Root(), state.NewDatabase(db), nil)
chainConfig = gen.Config chainConfig = gen.Config
} else { } else {

View file

@ -244,7 +244,6 @@ func TestT8n(t *testing.T) {
expExitCode: 3, expExitCode: 3,
}, },
} { } {
args := []string{"t8n"} args := []string{"t8n"}
args = append(args, tc.output.get()...) args = append(args, tc.output.get()...)
args = append(args, tc.input.get(tc.base)...) args = append(args, tc.input.get(tc.base)...)
@ -355,7 +354,6 @@ func TestT9n(t *testing.T) {
expExitCode: t8ntool.ErrorIO, expExitCode: t8ntool.ErrorIO,
}, },
} { } {
args := []string{"t9n"} args := []string{"t9n"}
args = append(args, tc.input.get(tc.base)...) args = append(args, tc.input.get(tc.base)...)
@ -475,7 +473,6 @@ func TestB11r(t *testing.T) {
expOut: "exp.json", expOut: "exp.json",
}, },
} { } {
args := []string{"b11r"} args := []string{"b11r"}
args = append(args, tc.input.get(tc.base)...) args = append(args, tc.input.get(tc.base)...)

View file

@ -248,7 +248,7 @@ func newFaucet(genesis *core.Genesis, port int, enodes []*enode.Node, network ui
cfg.SyncMode = downloader.LightSync cfg.SyncMode = downloader.LightSync
cfg.NetworkId = network cfg.NetworkId = network
cfg.Genesis = genesis cfg.Genesis = genesis
utils.SetDNSDiscoveryDefaults(&cfg, genesis.ToBlock(nil).Hash()) utils.SetDNSDiscoveryDefaults(&cfg, genesis.ToBlock().Hash())
lesBackend, err := les.New(stack, &cfg) lesBackend, err := les.New(stack, &cfg)
if err != nil { if err != nil {
@ -709,7 +709,7 @@ func authTwitter(url string, tokenV1, tokenV2 string) (string, string, string, c
case tokenV2 != "": case tokenV2 != "":
return authTwitterWithTokenV2(tweetID, tokenV2) return authTwitterWithTokenV2(tweetID, tokenV2)
} }
// Twiter API token isn't provided so we just load the public posts // Twitter API token isn't provided so we just load the public posts
// and scrape it for the Ethereum address and profile URL. We need to load // and scrape it for the Ethereum address and profile URL. We need to load
// the mobile page though since the main page loads tweet contents via JS. // the mobile page though since the main page loads tweet contents via JS.
url = strings.Replace(url, "https://twitter.com/", "https://mobile.twitter.com/", 1) url = strings.Replace(url, "https://twitter.com/", "https://mobile.twitter.com/", 1)

View file

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
@ -69,7 +70,7 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to
Name: "import", Name: "import",
Usage: "Import a blockchain file", Usage: "Import a blockchain file",
ArgsUsage: "<filename> (<filename 2> ... <filename N>) ", ArgsUsage: "<filename> (<filename 2> ... <filename N>) ",
Flags: append([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CacheFlag, utils.CacheFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
utils.GCModeFlag, utils.GCModeFlag,
@ -91,7 +92,7 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to
utils.MetricsInfluxDBBucketFlag, utils.MetricsInfluxDBBucketFlag,
utils.MetricsInfluxDBOrganizationFlag, utils.MetricsInfluxDBOrganizationFlag,
utils.TxLookupLimitFlag, utils.TxLookupLimitFlag,
}, utils.DatabasePathFlags...), }, utils.DatabasePathFlags),
Description: ` Description: `
The import command imports blocks from an RLP-encoded form. The form can be one file The import command imports blocks from an RLP-encoded form. The form can be one file
with several RLP-encoded blocks, or several files can be used. with several RLP-encoded blocks, or several files can be used.
@ -104,10 +105,10 @@ processing will proceed even if an individual RLP-file import failure occurs.`,
Name: "export", Name: "export",
Usage: "Export blockchain into file", Usage: "Export blockchain into file",
ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]", ArgsUsage: "<filename> [<blockNumFirst> <blockNumLast>]",
Flags: append([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CacheFlag, utils.CacheFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.DatabasePathFlags...), }, utils.DatabasePathFlags),
Description: ` Description: `
Requires a first argument of the file to write to. Requires a first argument of the file to write to.
Optional second and third arguments control the first and Optional second and third arguments control the first and
@ -120,10 +121,10 @@ be gzipped.`,
Name: "import-preimages", Name: "import-preimages",
Usage: "Import the preimage database from an RLP stream", Usage: "Import the preimage database from an RLP stream",
ArgsUsage: "<datafile>", ArgsUsage: "<datafile>",
Flags: append([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CacheFlag, utils.CacheFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.DatabasePathFlags...), }, utils.DatabasePathFlags),
Description: ` Description: `
The import-preimages command imports hash preimages from an RLP encoded stream. The import-preimages command imports hash preimages from an RLP encoded stream.
It's deprecated, please use "geth db import" instead. It's deprecated, please use "geth db import" instead.
@ -134,10 +135,10 @@ It's deprecated, please use "geth db import" instead.
Name: "export-preimages", Name: "export-preimages",
Usage: "Export the preimage database into an RLP stream", Usage: "Export the preimage database into an RLP stream",
ArgsUsage: "<dumpfile>", ArgsUsage: "<dumpfile>",
Flags: append([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CacheFlag, utils.CacheFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.DatabasePathFlags...), }, utils.DatabasePathFlags),
Description: ` Description: `
The export-preimages command exports hash preimages to an RLP encoded stream. The export-preimages command exports hash preimages to an RLP encoded stream.
It's deprecated, please use "geth db export" instead. It's deprecated, please use "geth db export" instead.
@ -148,7 +149,7 @@ It's deprecated, please use "geth db export" instead.
Name: "dump", Name: "dump",
Usage: "Dump a specific block from storage", Usage: "Dump a specific block from storage",
ArgsUsage: "[? <blockHash> | <blockNum>]", ArgsUsage: "[? <blockHash> | <blockNum>]",
Flags: append([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CacheFlag, utils.CacheFlag,
utils.IterativeOutputFlag, utils.IterativeOutputFlag,
utils.ExcludeCodeFlag, utils.ExcludeCodeFlag,
@ -156,7 +157,7 @@ It's deprecated, please use "geth db export" instead.
utils.IncludeIncompletesFlag, utils.IncludeIncompletesFlag,
utils.StartKeyFlag, utils.StartKeyFlag,
utils.DumpLimitFlag, utils.DumpLimitFlag,
}, utils.DatabasePathFlags...), }, utils.DatabasePathFlags),
Description: ` Description: `
This command dumps out the state for a given block (or latest, if none provided). This command dumps out the state for a given block (or latest, if none provided).
`, `,
@ -383,12 +384,12 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node) (*state.DumpConfig, eth
return nil, nil, common.Hash{}, fmt.Errorf("block %x not found", hash) return nil, nil, common.Hash{}, fmt.Errorf("block %x not found", hash)
} }
} else { } else {
number, err := strconv.Atoi(arg) number, err := strconv.ParseUint(arg, 10, 64)
if err != nil { if err != nil {
return nil, nil, common.Hash{}, err return nil, nil, common.Hash{}, err
} }
if hash := rawdb.ReadCanonicalHash(db, uint64(number)); hash != (common.Hash{}) { if hash := rawdb.ReadCanonicalHash(db, number); hash != (common.Hash{}) {
header = rawdb.ReadHeader(db, hash, uint64(number)) header = rawdb.ReadHeader(db, hash, number)
} else { } else {
return nil, nil, common.Hash{}, fmt.Errorf("header for block %d not found", number) return nil, nil, common.Hash{}, fmt.Errorf("header for block %d not found", number)
} }

View file

@ -20,7 +20,6 @@ import (
"bufio" "bufio"
"errors" "errors"
"fmt" "fmt"
"math/big"
"os" "os"
"reflect" "reflect"
"unicode" "unicode"
@ -49,7 +48,7 @@ var (
Name: "dumpconfig", Name: "dumpconfig",
Usage: "Show configuration values", Usage: "Show configuration values",
ArgsUsage: "", ArgsUsage: "",
Flags: utils.GroupFlags(nodeFlags, rpcFlags), Flags: flags.Merge(nodeFlags, rpcFlags),
Description: `The dumpconfig command shows configuration values.`, Description: `The dumpconfig command shows configuration values.`,
} }
@ -157,13 +156,16 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
// makeFullNode loads geth configuration and creates the Ethereum backend. // makeFullNode loads geth configuration and creates the Ethereum backend.
func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
stack, cfg := makeConfigNode(ctx) stack, cfg := makeConfigNode(ctx)
if ctx.IsSet(utils.OverrideGrayGlacierFlag.Name) {
cfg.Eth.OverrideGrayGlacier = new(big.Int).SetUint64(ctx.Uint64(utils.OverrideGrayGlacierFlag.Name))
}
if ctx.IsSet(utils.OverrideTerminalTotalDifficulty.Name) { if ctx.IsSet(utils.OverrideTerminalTotalDifficulty.Name) {
cfg.Eth.OverrideTerminalTotalDifficulty = flags.GlobalBig(ctx, utils.OverrideTerminalTotalDifficulty.Name) cfg.Eth.OverrideTerminalTotalDifficulty = flags.GlobalBig(ctx, utils.OverrideTerminalTotalDifficulty.Name)
} }
if ctx.IsSet(utils.OverrideTerminalTotalDifficultyPassed.Name) {
override := ctx.Bool(utils.OverrideTerminalTotalDifficultyPassed.Name)
cfg.Eth.OverrideTerminalTotalDifficultyPassed = &override
}
backend, eth := utils.RegisterEthService(stack, &cfg.Eth) backend, eth := utils.RegisterEthService(stack, &cfg.Eth)
// Warn users to migrate if they have a legacy freezer format. // Warn users to migrate if they have a legacy freezer format.
if eth != nil && !ctx.IsSet(utils.IgnoreLegacyReceiptsFlag.Name) { if eth != nil && !ctx.IsSet(utils.IgnoreLegacyReceiptsFlag.Name) {
firstIdx := uint64(0) firstIdx := uint64(0)
@ -173,19 +175,24 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
if cfg.Eth.NetworkId == 1 && ghash == params.MainnetGenesisHash { if cfg.Eth.NetworkId == 1 && ghash == params.MainnetGenesisHash {
firstIdx = 46147 firstIdx = 46147
} }
isLegacy, _, err := dbHasLegacyReceipts(eth.ChainDb(), firstIdx) isLegacy, firstLegacy, err := dbHasLegacyReceipts(eth.ChainDb(), firstIdx)
if err != nil { if err != nil {
log.Error("Failed to check db for legacy receipts", "err", err) log.Error("Failed to check db for legacy receipts", "err", err)
} else if isLegacy { } else if isLegacy {
stack.Close() stack.Close()
utils.Fatalf("Database has receipts with a legacy format. Please run `geth db freezer-migrate`.") log.Error("Database has receipts with a legacy format", "firstLegacy", firstLegacy)
utils.Fatalf("Aborting. Please run `geth db freezer-migrate`.")
} }
} }
// Configure GraphQL if requested // Configure log filter RPC API.
filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth)
// Configure GraphQL if requested.
if ctx.IsSet(utils.GraphQLEnabledFlag.Name) { if ctx.IsSet(utils.GraphQLEnabledFlag.Name) {
utils.RegisterGraphQLService(stack, backend, cfg.Node) utils.RegisterGraphQLService(stack, backend, filterSystem, &cfg.Node)
} }
// Add the Ethereum Stats daemon if requested. // Add the Ethereum Stats daemon if requested.
if cfg.Ethstats.URL != "" { if cfg.Ethstats.URL != "" {
utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL) utils.RegisterEthStatsService(stack, backend, cfg.Ethstats.URL)

View file

@ -22,6 +22,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/console" "github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -34,7 +35,7 @@ var (
Action: localConsole, Action: localConsole,
Name: "console", Name: "console",
Usage: "Start an interactive JavaScript environment", Usage: "Start an interactive JavaScript environment",
Flags: utils.GroupFlags(nodeFlags, rpcFlags, consoleFlags), Flags: flags.Merge(nodeFlags, rpcFlags, consoleFlags),
Description: ` Description: `
The Geth console is an interactive shell for the JavaScript runtime environment The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the Ðapp JavaScript API. which exposes a node admin interface as well as the Ðapp JavaScript API.
@ -46,7 +47,7 @@ See https://geth.ethereum.org/docs/interface/javascript-console.`,
Name: "attach", Name: "attach",
Usage: "Start an interactive JavaScript environment (connect to node)", Usage: "Start an interactive JavaScript environment (connect to node)",
ArgsUsage: "[endpoint]", ArgsUsage: "[endpoint]",
Flags: utils.GroupFlags([]cli.Flag{utils.DataDirFlag}, consoleFlags), Flags: flags.Merge([]cli.Flag{utils.DataDirFlag}, consoleFlags),
Description: ` Description: `
The Geth console is an interactive shell for the JavaScript runtime environment The Geth console is an interactive shell for the JavaScript runtime environment
which exposes a node admin interface as well as the Ðapp JavaScript API. which exposes a node admin interface as well as the Ðapp JavaScript API.
@ -59,7 +60,7 @@ This command allows to open a console on a running geth node.`,
Name: "js", Name: "js",
Usage: "(DEPRECATED) Execute the specified JavaScript files", Usage: "(DEPRECATED) Execute the specified JavaScript files",
ArgsUsage: "<jsfile> [jsfile...]", ArgsUsage: "<jsfile> [jsfile...]",
Flags: utils.GroupFlags(nodeFlags, consoleFlags), Flags: flags.Merge(nodeFlags, consoleFlags),
Description: ` Description: `
The JavaScript VM exposes a node admin interface as well as the Ðapp The JavaScript VM exposes a node admin interface as well as the Ðapp
JavaScript API. See https://geth.ethereum.org/docs/interface/javascript-console`, JavaScript API. See https://geth.ethereum.org/docs/interface/javascript-console`,

View file

@ -41,7 +41,7 @@ func runMinimalGeth(t *testing.T, args ...string) *testgeth {
// --ropsten to make the 'writing genesis to disk' faster (no accounts) // --ropsten to make the 'writing genesis to disk' faster (no accounts)
// --networkid=1337 to avoid cache bump // --networkid=1337 to avoid cache bump
// --syncmode=full to avoid allocating fast sync bloom // --syncmode=full to avoid allocating fast sync bloom
allArgs := []string{"--ropsten", "--networkid", "1337", "--syncmode=full", "--port", "0", allArgs := []string{"--ropsten", "--networkid", "1337", "--authrpc.port", "0", "--syncmode=full", "--port", "0",
"--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64", "--nat", "none", "--nodiscover", "--maxpeers", "0", "--cache", "64",
"--datadir.minfreedisk", "0"} "--datadir.minfreedisk", "0"}
return runGeth(t, append(allArgs, args...)...) return runGeth(t, append(allArgs, args...)...)
@ -155,7 +155,7 @@ To exit, press ctrl-d or type exit
} }
// trulyRandInt generates a crypto random integer used by the console tests to // trulyRandInt generates a crypto random integer used by the console tests to
// not clash network ports with other tests running cocurrently. // not clash network ports with other tests running concurrently.
func trulyRandInt(lo, hi int) int { func trulyRandInt(lo, hi int) int {
num, _ := rand.Int(rand.Reader, big.NewInt(int64(hi-lo))) num, _ := rand.Int(rand.Reader, big.NewInt(int64(hi-lo)))
return int(num.Int64()) + lo return int(num.Int64()) + lo

View file

@ -22,7 +22,6 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"sort"
"strconv" "strconv"
"strings" "strings"
"syscall" "syscall"
@ -37,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
@ -77,7 +77,7 @@ Remove blockchain and state databases`,
Action: inspect, Action: inspect,
Name: "inspect", Name: "inspect",
ArgsUsage: "<prefix> <start>", ArgsUsage: "<prefix> <start>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Usage: "Inspect the storage size for each type of data in the database", Usage: "Inspect the storage size for each type of data in the database",
@ -87,7 +87,7 @@ Remove blockchain and state databases`,
Action: checkStateContent, Action: checkStateContent,
Name: "check-state-content", Name: "check-state-content",
ArgsUsage: "<start (optional)>", ArgsUsage: "<start (optional)>",
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags), Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Usage: "Verify that state data is cryptographically correct", Usage: "Verify that state data is cryptographically correct",
Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes. Description: `This command iterates the entire database for 32-byte keys, looking for rlp-encoded trie nodes.
For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates For each trie node encountered, it checks that the key corresponds to the keccak256(value). If this is not true, this indicates
@ -97,7 +97,7 @@ a data corruption.`,
Action: dbStats, Action: dbStats,
Name: "stats", Name: "stats",
Usage: "Print leveldb statistics", Usage: "Print leveldb statistics",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
} }
@ -105,7 +105,7 @@ a data corruption.`,
Action: dbCompact, Action: dbCompact,
Name: "compact", Name: "compact",
Usage: "Compact leveldb database. WARNING: May take a very long time", Usage: "Compact leveldb database. WARNING: May take a very long time",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
utils.CacheFlag, utils.CacheFlag,
utils.CacheDatabaseFlag, utils.CacheDatabaseFlag,
@ -119,7 +119,7 @@ corruption if it is aborted during execution'!`,
Name: "get", Name: "get",
Usage: "Show the value of a database key", Usage: "Show the value of a database key",
ArgsUsage: "<hex-encoded key>", ArgsUsage: "<hex-encoded key>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "This command looks up the specified database key from the database.", Description: "This command looks up the specified database key from the database.",
@ -129,7 +129,7 @@ corruption if it is aborted during execution'!`,
Name: "delete", Name: "delete",
Usage: "Delete a database key (WARNING: may corrupt your database)", Usage: "Delete a database key (WARNING: may corrupt your database)",
ArgsUsage: "<hex-encoded key>", ArgsUsage: "<hex-encoded key>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `This command deletes the specified database key from the database. Description: `This command deletes the specified database key from the database.
@ -140,7 +140,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Name: "put", Name: "put",
Usage: "Set the value of a database key (WARNING: may corrupt your database)", Usage: "Set the value of a database key (WARNING: may corrupt your database)",
ArgsUsage: "<hex-encoded key> <hex-encoded value>", ArgsUsage: "<hex-encoded key> <hex-encoded value>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `This command sets a given database key to the given value. Description: `This command sets a given database key to the given value.
@ -151,7 +151,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Name: "dumptrie", Name: "dumptrie",
Usage: "Show the storage key/values of a given storage trie", Usage: "Show the storage key/values of a given storage trie",
ArgsUsage: "<hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>", ArgsUsage: "<hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "This command looks up the specified database key from the database.", Description: "This command looks up the specified database key from the database.",
@ -159,9 +159,9 @@ WARNING: This is a low-level operation which may cause database corruption!`,
dbDumpFreezerIndex = &cli.Command{ dbDumpFreezerIndex = &cli.Command{
Action: freezerInspect, Action: freezerInspect,
Name: "freezer-index", Name: "freezer-index",
Usage: "Dump out the index of a given freezer type", Usage: "Dump out the index of a specific freezer table",
ArgsUsage: "<type> <start (int)> <end (int)>", ArgsUsage: "<freezer-type> <table-type> <start (int)> <end (int)>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "This command displays information about the freezer index.", Description: "This command displays information about the freezer index.",
@ -171,7 +171,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Name: "import", Name: "import",
Usage: "Imports leveldb-data from an exported RLP dump.", Usage: "Imports leveldb-data from an exported RLP dump.",
ArgsUsage: "<dumpfile> <start (optional)", ArgsUsage: "<dumpfile> <start (optional)",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "The import command imports the specific chain data from an RLP encoded stream.", Description: "The import command imports the specific chain data from an RLP encoded stream.",
@ -181,7 +181,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Name: "export", Name: "export",
Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.", Usage: "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used.",
ArgsUsage: "<type> <dumpfile>", ArgsUsage: "<type> <dumpfile>",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.", Description: "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed.",
@ -190,7 +190,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Action: showMetaData, Action: showMetaData,
Name: "metadata", Name: "metadata",
Usage: "Shows metadata about the chain status.", Usage: "Shows metadata about the chain status.",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: "Shows metadata about the chain status.", Description: "Shows metadata about the chain status.",
@ -200,7 +200,7 @@ WARNING: This is a low-level operation which may cause database corruption!`,
Name: "freezer-migrate", Name: "freezer-migrate",
Usage: "Migrate legacy parts of the freezer. (WARNING: may take a long time)", Usage: "Migrate legacy parts of the freezer. (WARNING: may take a long time)",
ArgsUsage: "", ArgsUsage: "",
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.SyncModeFlag, utils.SyncModeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
Description: `The freezer-migrate command checks your database for receipts in a legacy format and updates those. Description: `The freezer-migrate command checks your database for receipts in a legacy format and updates those.
@ -274,7 +274,7 @@ func inspect(ctx *cli.Context) error {
start []byte start []byte
) )
if ctx.NArg() > 2 { if ctx.NArg() > 2 {
return fmt.Errorf("Max 2 arguments: %v", ctx.Command.ArgsUsage) return fmt.Errorf("max 2 arguments: %v", ctx.Command.ArgsUsage)
} }
if ctx.NArg() >= 1 { if ctx.NArg() >= 1 {
if d, err := hexutil.Decode(ctx.Args().Get(0)); err != nil { if d, err := hexutil.Decode(ctx.Args().Get(0)); err != nil {
@ -535,43 +535,35 @@ func dbDumpTrie(ctx *cli.Context) error {
} }
func freezerInspect(ctx *cli.Context) error { func freezerInspect(ctx *cli.Context) error {
var ( if ctx.NArg() < 4 {
start, end int64
disableSnappy bool
err error
)
if ctx.NArg() < 3 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage) return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
} }
kind := ctx.Args().Get(0) var (
if noSnap, ok := rawdb.FreezerNoSnappy[kind]; !ok { freezer = ctx.Args().Get(0)
var options []string table = ctx.Args().Get(1)
for opt := range rawdb.FreezerNoSnappy { )
options = append(options, opt) start, err := strconv.ParseInt(ctx.Args().Get(2), 10, 64)
} if err != nil {
sort.Strings(options) log.Info("Could not read start-param", "err", err)
return fmt.Errorf("Could read freezer-type '%v'. Available options: %v", kind, options)
} else {
disableSnappy = noSnap
}
if start, err = strconv.ParseInt(ctx.Args().Get(1), 10, 64); err != nil {
log.Info("Could read start-param", "error", err)
return err return err
} }
if end, err = strconv.ParseInt(ctx.Args().Get(2), 10, 64); err != nil { end, err := strconv.ParseInt(ctx.Args().Get(3), 10, 64)
log.Info("Could read count param", "error", err) if err != nil {
log.Info("Could not read count param", "err", err)
return err return err
} }
stack, _ := makeConfigNode(ctx) stack, _ := makeConfigNode(ctx)
defer stack.Close() defer stack.Close()
path := filepath.Join(stack.ResolvePath("chaindata"), "ancient")
log.Info("Opening freezer", "location", path, "name", kind) db := utils.MakeChainDatabase(ctx, stack, true)
if f, err := rawdb.NewFreezerTable(path, kind, disableSnappy, true); err != nil { defer db.Close()
ancient, err := db.AncientDatadir()
if err != nil {
log.Info("Failed to retrieve ancient root", "err", err)
return err return err
} else {
f.DumpIndex(start, end)
} }
return nil return rawdb.InspectFreezerTable(ancient, freezer, table, start, end)
} }
func importLDBdata(ctx *cli.Context) error { func importLDBdata(ctx *cli.Context) error {
@ -830,11 +822,15 @@ func dbHasLegacyReceipts(db ethdb.Database, firstIdx uint64) (bool, uint64, erro
} }
} }
} }
// Is first non-empty receipt legacy?
first, err := db.Ancient("receipts", firstIdx) first, err := db.Ancient("receipts", firstIdx)
if err != nil { if err != nil {
return false, 0, err return false, 0, err
} }
// We looped over all receipts and they were all empty
if bytes.Equal(first, emptyRLPList) {
return false, 0, nil
}
// Is first non-empty receipt legacy?
legacy, err = types.IsLegacyStoredReceipts(first) legacy, err = types.IsLegacyStoredReceipts(first)
return legacy, firstIdx, err return legacy, firstIdx, err
} }

View file

@ -83,7 +83,7 @@ func TestCustomGenesis(t *testing.T) {
// Query the custom genesis block // Query the custom genesis block
geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16", geth := runGeth(t, "--networkid", "1337", "--syncmode=full", "--cache", "16",
"--datadir", datadir, "--maxpeers", "0", "--port", "0", "--datadir", datadir, "--maxpeers", "0", "--port", "0", "--authrpc.port", "0",
"--nodiscover", "--nat", "none", "--ipcdisable", "--nodiscover", "--nat", "none", "--ipcdisable",
"--exec", tt.query, "console") "--exec", tt.query, "console")
geth.ExpectRegexp(tt.result) geth.ExpectRegexp(tt.result)

View file

@ -111,7 +111,7 @@ var nextIPC = uint32(0)
func startGethWithIpc(t *testing.T, name string, args ...string) *gethrpc { func startGethWithIpc(t *testing.T, name string, args ...string) *gethrpc {
ipcName := fmt.Sprintf("geth-%d.ipc", atomic.AddUint32(&nextIPC, 1)) ipcName := fmt.Sprintf("geth-%d.ipc", atomic.AddUint32(&nextIPC, 1))
args = append([]string{"--networkid=42", "--port=0", "--ipcpath", ipcName}, args...) args = append([]string{"--networkid=42", "--port=0", "--authrpc.port", "0", "--ipcpath", ipcName}, args...)
t.Logf("Starting %v with rpc: %v", name, args) t.Logf("Starting %v with rpc: %v", name, args)
g := &gethrpc{ g := &gethrpc{

View file

@ -58,7 +58,7 @@ var (
// The app that holds all commands and flags. // The app that holds all commands and flags.
app = flags.NewApp(gitCommit, gitDate, "the go-ethereum command line interface") app = flags.NewApp(gitCommit, gitDate, "the go-ethereum command line interface")
// flags that configure the node // flags that configure the node
nodeFlags = utils.GroupFlags([]cli.Flag{ nodeFlags = flags.Merge([]cli.Flag{
utils.IdentityFlag, utils.IdentityFlag,
utils.UnlockedAccountFlag, utils.UnlockedAccountFlag,
utils.PasswordFileFlag, utils.PasswordFileFlag,
@ -69,8 +69,8 @@ var (
utils.NoUSBFlag, utils.NoUSBFlag,
utils.USBFlag, utils.USBFlag,
utils.SmartCardDaemonPathFlag, utils.SmartCardDaemonPathFlag,
utils.OverrideGrayGlacierFlag,
utils.OverrideTerminalTotalDifficulty, utils.OverrideTerminalTotalDifficulty,
utils.OverrideTerminalTotalDifficultyPassed,
utils.EthashCacheDirFlag, utils.EthashCacheDirFlag,
utils.EthashCachesInMemoryFlag, utils.EthashCachesInMemoryFlag,
utils.EthashCachesOnDiskFlag, utils.EthashCachesOnDiskFlag,
@ -117,6 +117,7 @@ var (
utils.CacheSnapshotFlag, utils.CacheSnapshotFlag,
utils.CacheNoPrefetchFlag, utils.CacheNoPrefetchFlag,
utils.CachePreimagesFlag, utils.CachePreimagesFlag,
utils.CacheLogSizeFlag,
utils.FDLimitFlag, utils.FDLimitFlag,
utils.ListenPortFlag, utils.ListenPortFlag,
utils.DiscoveryPortFlag, utils.DiscoveryPortFlag,
@ -243,7 +244,7 @@ func init() {
} }
sort.Sort(cli.CommandsByName(app.Commands)) sort.Sort(cli.CommandsByName(app.Commands))
app.Flags = utils.GroupFlags( app.Flags = flags.Merge(
nodeFlags, nodeFlags,
rpcFlags, rpcFlags,
consoleFlags, consoleFlags,

View file

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/state/snapshot"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
@ -56,7 +57,7 @@ var (
Usage: "Prune stale ethereum state data based on the snapshot", Usage: "Prune stale ethereum state data based on the snapshot",
ArgsUsage: "<root>", ArgsUsage: "<root>",
Action: pruneState, Action: pruneState,
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.CacheTrieJournalFlag, utils.CacheTrieJournalFlag,
utils.BloomFilterSizeFlag, utils.BloomFilterSizeFlag,
}, utils.NetworkFlags, utils.DatabasePathFlags), }, utils.NetworkFlags, utils.DatabasePathFlags),
@ -80,7 +81,7 @@ the trie clean cache with default directory will be deleted.
Usage: "Recalculate state hash based on the snapshot for verification", Usage: "Recalculate state hash based on the snapshot for verification",
ArgsUsage: "<root>", ArgsUsage: "<root>",
Action: verifyState, Action: verifyState,
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags), Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Description: ` Description: `
geth snapshot verify-state <state-root> geth snapshot verify-state <state-root>
will traverse the whole accounts and storages set based on the specified will traverse the whole accounts and storages set based on the specified
@ -93,7 +94,7 @@ In other words, this command does the snapshot to trie conversion.
Usage: "Check that there is no 'dangling' snap storage", Usage: "Check that there is no 'dangling' snap storage",
ArgsUsage: "<root>", ArgsUsage: "<root>",
Action: checkDanglingStorage, Action: checkDanglingStorage,
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags), Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Description: ` Description: `
geth snapshot check-dangling-storage <state-root> traverses the snap storage geth snapshot check-dangling-storage <state-root> traverses the snap storage
data, and verifies that all snapshot storage data has a corresponding account. data, and verifies that all snapshot storage data has a corresponding account.
@ -104,7 +105,7 @@ data, and verifies that all snapshot storage data has a corresponding account.
Usage: "Check all snapshot layers for the a specific account", Usage: "Check all snapshot layers for the a specific account",
ArgsUsage: "<address | hash>", ArgsUsage: "<address | hash>",
Action: checkAccount, Action: checkAccount,
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags), Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Description: ` Description: `
geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out geth snapshot inspect-account <address | hash> checks all snapshot layers and prints out
information about the specified address. information about the specified address.
@ -115,7 +116,7 @@ information about the specified address.
Usage: "Traverse the state with given root hash and perform quick verification", Usage: "Traverse the state with given root hash and perform quick verification",
ArgsUsage: "<root>", ArgsUsage: "<root>",
Action: traverseState, Action: traverseState,
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags), Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Description: ` Description: `
geth snapshot traverse-state <state-root> geth snapshot traverse-state <state-root>
will traverse the whole state from the given state root and will abort if any will traverse the whole state from the given state root and will abort if any
@ -130,7 +131,7 @@ It's also usable without snapshot enabled.
Usage: "Traverse the state with given root hash and perform detailed verification", Usage: "Traverse the state with given root hash and perform detailed verification",
ArgsUsage: "<root>", ArgsUsage: "<root>",
Action: traverseRawState, Action: traverseRawState,
Flags: utils.GroupFlags(utils.NetworkFlags, utils.DatabasePathFlags), Flags: flags.Merge(utils.NetworkFlags, utils.DatabasePathFlags),
Description: ` Description: `
geth snapshot traverse-rawstate <state-root> geth snapshot traverse-rawstate <state-root>
will traverse the whole state from the given root and will abort if any referenced will traverse the whole state from the given root and will abort if any referenced
@ -146,7 +147,7 @@ It's also usable without snapshot enabled.
Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)", Usage: "Dump a specific block from storage (same as 'geth dump' but using snapshots)",
ArgsUsage: "[? <blockHash> | <blockNum>]", ArgsUsage: "[? <blockHash> | <blockNum>]",
Action: dumpState, Action: dumpState,
Flags: utils.GroupFlags([]cli.Flag{ Flags: flags.Merge([]cli.Flag{
utils.ExcludeCodeFlag, utils.ExcludeCodeFlag,
utils.ExcludeStorageFlag, utils.ExcludeStorageFlag,
utils.StartKeyFlag, utils.StartKeyFlag,
@ -270,7 +271,7 @@ func traverseState(ctx *cli.Context) error {
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64()) log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
} }
triedb := trie.NewDatabase(chaindb) triedb := trie.NewDatabase(chaindb)
t, err := trie.NewSecure(common.Hash{}, root, triedb) t, err := trie.NewStateTrie(common.Hash{}, root, triedb)
if err != nil { if err != nil {
log.Error("Failed to open trie", "root", root, "err", err) log.Error("Failed to open trie", "root", root, "err", err)
return err return err
@ -291,7 +292,7 @@ func traverseState(ctx *cli.Context) error {
return err return err
} }
if acc.Root != emptyRoot { if acc.Root != emptyRoot {
storageTrie, err := trie.NewSecure(common.BytesToHash(accIter.Key), acc.Root, triedb) storageTrie, err := trie.NewStateTrie(common.BytesToHash(accIter.Key), acc.Root, triedb)
if err != nil { if err != nil {
log.Error("Failed to open storage trie", "root", acc.Root, "err", err) log.Error("Failed to open storage trie", "root", acc.Root, "err", err)
return err return err
@ -359,7 +360,7 @@ func traverseRawState(ctx *cli.Context) error {
log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64()) log.Info("Start traversing the state", "root", root, "number", headBlock.NumberU64())
} }
triedb := trie.NewDatabase(chaindb) triedb := trie.NewDatabase(chaindb)
t, err := trie.NewSecure(common.Hash{}, root, triedb) t, err := trie.NewStateTrie(common.Hash{}, root, triedb)
if err != nil { if err != nil {
log.Error("Failed to open trie", "root", root, "err", err) log.Error("Failed to open trie", "root", root, "err", err)
return err return err
@ -405,7 +406,7 @@ func traverseRawState(ctx *cli.Context) error {
return errors.New("invalid account") return errors.New("invalid account")
} }
if acc.Root != emptyRoot { if acc.Root != emptyRoot {
storageTrie, err := trie.NewSecure(common.BytesToHash(accIter.LeafKey()), acc.Root, triedb) storageTrie, err := trie.NewStateTrie(common.BytesToHash(accIter.LeafKey()), acc.Root, triedb)
if err != nil { if err != nil {
log.Error("Failed to open storage trie", "root", acc.Root, "err", err) log.Error("Failed to open storage trie", "root", acc.Root, "err", err)
return errors.New("missing storage trie") return errors.New("missing storage trie")

View file

@ -118,7 +118,6 @@ func TestMatching(t *testing.T) {
version, vuln.Introduced, vuln.Fixed, vuln.Name, vulnIntro, current, vulnFixed) version, vuln.Introduced, vuln.Fixed, vuln.Name, vulnIntro, current, vulnFixed)
} }
} }
} }
} }
for major := 1; major < 2; major++ { for major := 1; major < 2; major++ {

View file

@ -1,626 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"errors"
"math"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
math2 "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
// alethGenesisSpec represents the genesis specification format used by the
// C++ Ethereum implementation.
type alethGenesisSpec struct {
SealEngine string `json:"sealEngine"`
Params struct {
AccountStartNonce math2.HexOrDecimal64 `json:"accountStartNonce"`
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
HomesteadForkBlock *hexutil.Big `json:"homesteadForkBlock,omitempty"`
DaoHardforkBlock math2.HexOrDecimal64 `json:"daoHardforkBlock"`
EIP150ForkBlock *hexutil.Big `json:"EIP150ForkBlock,omitempty"`
EIP158ForkBlock *hexutil.Big `json:"EIP158ForkBlock,omitempty"`
ByzantiumForkBlock *hexutil.Big `json:"byzantiumForkBlock,omitempty"`
ConstantinopleForkBlock *hexutil.Big `json:"constantinopleForkBlock,omitempty"`
ConstantinopleFixForkBlock *hexutil.Big `json:"constantinopleFixForkBlock,omitempty"`
IstanbulForkBlock *hexutil.Big `json:"istanbulForkBlock,omitempty"`
MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
MaxGasLimit hexutil.Uint64 `json:"maxGasLimit"`
TieBreakingGas bool `json:"tieBreakingGas"`
GasLimitBoundDivisor math2.HexOrDecimal64 `json:"gasLimitBoundDivisor"`
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
DifficultyBoundDivisor *math2.HexOrDecimal256 `json:"difficultyBoundDivisor"`
DurationLimit *math2.HexOrDecimal256 `json:"durationLimit"`
BlockReward *hexutil.Big `json:"blockReward"`
NetworkID hexutil.Uint64 `json:"networkID"`
ChainID hexutil.Uint64 `json:"chainID"`
AllowFutureBlocks bool `json:"allowFutureBlocks"`
} `json:"params"`
Genesis struct {
Nonce types.BlockNonce `json:"nonce"`
Difficulty *hexutil.Big `json:"difficulty"`
MixHash common.Hash `json:"mixHash"`
Author common.Address `json:"author"`
Timestamp hexutil.Uint64 `json:"timestamp"`
ParentHash common.Hash `json:"parentHash"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
} `json:"genesis"`
Accounts map[common.UnprefixedAddress]*alethGenesisSpecAccount `json:"accounts"`
}
// alethGenesisSpecAccount is the prefunded genesis account and/or precompiled
// contract definition.
type alethGenesisSpecAccount struct {
Balance *math2.HexOrDecimal256 `json:"balance,omitempty"`
Nonce uint64 `json:"nonce,omitempty"`
Precompiled *alethGenesisSpecBuiltin `json:"precompiled,omitempty"`
}
// alethGenesisSpecBuiltin is the precompiled contract definition.
type alethGenesisSpecBuiltin struct {
Name string `json:"name,omitempty"`
StartingBlock *hexutil.Big `json:"startingBlock,omitempty"`
Linear *alethGenesisSpecLinearPricing `json:"linear,omitempty"`
}
type alethGenesisSpecLinearPricing struct {
Base uint64 `json:"base"`
Word uint64 `json:"word"`
}
// newAlethGenesisSpec converts a go-ethereum genesis block into a Aleth-specific
// chain specification format.
func newAlethGenesisSpec(network string, genesis *core.Genesis) (*alethGenesisSpec, error) {
// Only ethash is currently supported between go-ethereum and aleth
if genesis.Config.Ethash == nil {
return nil, errors.New("unsupported consensus engine")
}
// Reconstruct the chain spec in Aleth format
spec := &alethGenesisSpec{
SealEngine: "Ethash",
}
// Some defaults
spec.Params.AccountStartNonce = 0
spec.Params.TieBreakingGas = false
spec.Params.AllowFutureBlocks = false
// Dao hardfork block is a special one. The fork block is listed as 0 in the
// config but aleth will sync with ETC clients up until the actual dao hard
// fork block.
spec.Params.DaoHardforkBlock = 0
if num := genesis.Config.HomesteadBlock; num != nil {
spec.Params.HomesteadForkBlock = (*hexutil.Big)(num)
}
if num := genesis.Config.EIP150Block; num != nil {
spec.Params.EIP150ForkBlock = (*hexutil.Big)(num)
}
if num := genesis.Config.EIP158Block; num != nil {
spec.Params.EIP158ForkBlock = (*hexutil.Big)(num)
}
if num := genesis.Config.ByzantiumBlock; num != nil {
spec.Params.ByzantiumForkBlock = (*hexutil.Big)(num)
}
if num := genesis.Config.ConstantinopleBlock; num != nil {
spec.Params.ConstantinopleForkBlock = (*hexutil.Big)(num)
}
if num := genesis.Config.PetersburgBlock; num != nil {
spec.Params.ConstantinopleFixForkBlock = (*hexutil.Big)(num)
}
if num := genesis.Config.IstanbulBlock; num != nil {
spec.Params.IstanbulForkBlock = (*hexutil.Big)(num)
}
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.MaxGasLimit = (hexutil.Uint64)(math.MaxInt64)
spec.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Params.DifficultyBoundDivisor = (*math2.HexOrDecimal256)(params.DifficultyBoundDivisor)
spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
spec.Params.DurationLimit = (*math2.HexOrDecimal256)(params.DurationLimit)
spec.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
spec.Genesis.Nonce = types.EncodeNonce(genesis.Nonce)
spec.Genesis.MixHash = genesis.Mixhash
spec.Genesis.Difficulty = (*hexutil.Big)(genesis.Difficulty)
spec.Genesis.Author = genesis.Coinbase
spec.Genesis.Timestamp = (hexutil.Uint64)(genesis.Timestamp)
spec.Genesis.ParentHash = genesis.ParentHash
spec.Genesis.ExtraData = genesis.ExtraData
spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit)
for address, account := range genesis.Alloc {
spec.setAccount(address, account)
}
spec.setPrecompile(1, &alethGenesisSpecBuiltin{Name: "ecrecover",
Linear: &alethGenesisSpecLinearPricing{Base: 3000}})
spec.setPrecompile(2, &alethGenesisSpecBuiltin{Name: "sha256",
Linear: &alethGenesisSpecLinearPricing{Base: 60, Word: 12}})
spec.setPrecompile(3, &alethGenesisSpecBuiltin{Name: "ripemd160",
Linear: &alethGenesisSpecLinearPricing{Base: 600, Word: 120}})
spec.setPrecompile(4, &alethGenesisSpecBuiltin{Name: "identity",
Linear: &alethGenesisSpecLinearPricing{Base: 15, Word: 3}})
if genesis.Config.ByzantiumBlock != nil {
spec.setPrecompile(5, &alethGenesisSpecBuiltin{Name: "modexp",
StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock)})
spec.setPrecompile(6, &alethGenesisSpecBuiltin{Name: "alt_bn128_G1_add",
StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Linear: &alethGenesisSpecLinearPricing{Base: 500}})
spec.setPrecompile(7, &alethGenesisSpecBuiltin{Name: "alt_bn128_G1_mul",
StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Linear: &alethGenesisSpecLinearPricing{Base: 40000}})
spec.setPrecompile(8, &alethGenesisSpecBuiltin{Name: "alt_bn128_pairing_product",
StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock)})
}
if genesis.Config.IstanbulBlock != nil {
if genesis.Config.ByzantiumBlock == nil {
return nil, errors.New("invalid genesis, istanbul fork is enabled while byzantium is not")
}
spec.setPrecompile(6, &alethGenesisSpecBuiltin{
Name: "alt_bn128_G1_add",
StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
}) // Aleth hardcoded the gas policy
spec.setPrecompile(7, &alethGenesisSpecBuiltin{
Name: "alt_bn128_G1_mul",
StartingBlock: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
}) // Aleth hardcoded the gas policy
spec.setPrecompile(9, &alethGenesisSpecBuiltin{
Name: "blake2_compression",
StartingBlock: (*hexutil.Big)(genesis.Config.IstanbulBlock),
})
}
return spec, nil
}
func (spec *alethGenesisSpec) setPrecompile(address byte, data *alethGenesisSpecBuiltin) {
if spec.Accounts == nil {
spec.Accounts = make(map[common.UnprefixedAddress]*alethGenesisSpecAccount)
}
addr := common.UnprefixedAddress(common.BytesToAddress([]byte{address}))
if _, exist := spec.Accounts[addr]; !exist {
spec.Accounts[addr] = &alethGenesisSpecAccount{}
}
spec.Accounts[addr].Precompiled = data
}
func (spec *alethGenesisSpec) setAccount(address common.Address, account core.GenesisAccount) {
if spec.Accounts == nil {
spec.Accounts = make(map[common.UnprefixedAddress]*alethGenesisSpecAccount)
}
a, exist := spec.Accounts[common.UnprefixedAddress(address)]
if !exist {
a = &alethGenesisSpecAccount{}
spec.Accounts[common.UnprefixedAddress(address)] = a
}
a.Balance = (*math2.HexOrDecimal256)(account.Balance)
a.Nonce = account.Nonce
}
// parityChainSpec is the chain specification format used by Parity.
type parityChainSpec struct {
Name string `json:"name"`
Datadir string `json:"dataDir"`
Engine struct {
Ethash struct {
Params struct {
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
DurationLimit *hexutil.Big `json:"durationLimit"`
BlockReward map[string]string `json:"blockReward"`
DifficultyBombDelays map[string]string `json:"difficultyBombDelays"`
HomesteadTransition hexutil.Uint64 `json:"homesteadTransition"`
EIP100bTransition hexutil.Uint64 `json:"eip100bTransition"`
} `json:"params"`
} `json:"Ethash"`
} `json:"engine"`
Params struct {
AccountStartNonce hexutil.Uint64 `json:"accountStartNonce"`
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
GasLimitBoundDivisor math2.HexOrDecimal64 `json:"gasLimitBoundDivisor"`
NetworkID hexutil.Uint64 `json:"networkID"`
ChainID hexutil.Uint64 `json:"chainID"`
MaxCodeSize hexutil.Uint64 `json:"maxCodeSize"`
MaxCodeSizeTransition hexutil.Uint64 `json:"maxCodeSizeTransition"`
EIP98Transition hexutil.Uint64 `json:"eip98Transition"`
EIP150Transition hexutil.Uint64 `json:"eip150Transition"`
EIP160Transition hexutil.Uint64 `json:"eip160Transition"`
EIP161abcTransition hexutil.Uint64 `json:"eip161abcTransition"`
EIP161dTransition hexutil.Uint64 `json:"eip161dTransition"`
EIP155Transition hexutil.Uint64 `json:"eip155Transition"`
EIP140Transition hexutil.Uint64 `json:"eip140Transition"`
EIP211Transition hexutil.Uint64 `json:"eip211Transition"`
EIP214Transition hexutil.Uint64 `json:"eip214Transition"`
EIP658Transition hexutil.Uint64 `json:"eip658Transition"`
EIP145Transition hexutil.Uint64 `json:"eip145Transition"`
EIP1014Transition hexutil.Uint64 `json:"eip1014Transition"`
EIP1052Transition hexutil.Uint64 `json:"eip1052Transition"`
EIP1283Transition hexutil.Uint64 `json:"eip1283Transition"`
EIP1283DisableTransition hexutil.Uint64 `json:"eip1283DisableTransition"`
EIP1283ReenableTransition hexutil.Uint64 `json:"eip1283ReenableTransition"`
EIP1344Transition hexutil.Uint64 `json:"eip1344Transition"`
EIP1884Transition hexutil.Uint64 `json:"eip1884Transition"`
EIP2028Transition hexutil.Uint64 `json:"eip2028Transition"`
} `json:"params"`
Genesis struct {
Seal struct {
Ethereum struct {
Nonce types.BlockNonce `json:"nonce"`
MixHash hexutil.Bytes `json:"mixHash"`
} `json:"ethereum"`
} `json:"seal"`
Difficulty *hexutil.Big `json:"difficulty"`
Author common.Address `json:"author"`
Timestamp hexutil.Uint64 `json:"timestamp"`
ParentHash common.Hash `json:"parentHash"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
} `json:"genesis"`
Nodes []string `json:"nodes"`
Accounts map[common.UnprefixedAddress]*parityChainSpecAccount `json:"accounts"`
}
// parityChainSpecAccount is the prefunded genesis account and/or precompiled
// contract definition.
type parityChainSpecAccount struct {
Balance math2.HexOrDecimal256 `json:"balance"`
Nonce math2.HexOrDecimal64 `json:"nonce,omitempty"`
Builtin *parityChainSpecBuiltin `json:"builtin,omitempty"`
}
// parityChainSpecBuiltin is the precompiled contract definition.
type parityChainSpecBuiltin struct {
Name string `json:"name"` // Each builtin should has it own name
Pricing interface{} `json:"pricing"` // Each builtin should has it own price strategy
ActivateAt *hexutil.Big `json:"activate_at,omitempty"` // ActivateAt can't be omitted if empty, default means no fork
}
// parityChainSpecPricing represents the different pricing models that builtin
// contracts might advertise using.
type parityChainSpecPricing struct {
Linear *parityChainSpecLinearPricing `json:"linear,omitempty"`
ModExp *parityChainSpecModExpPricing `json:"modexp,omitempty"`
// Before the https://github.com/paritytech/parity-ethereum/pull/11039,
// Parity uses this format to config bn pairing price policy.
AltBnPairing *parityChainSepcAltBnPairingPricing `json:"alt_bn128_pairing,omitempty"`
// Blake2F is the price per round of Blake2 compression
Blake2F *parityChainSpecBlakePricing `json:"blake2_f,omitempty"`
}
type parityChainSpecLinearPricing struct {
Base uint64 `json:"base"`
Word uint64 `json:"word"`
}
type parityChainSpecModExpPricing struct {
Divisor uint64 `json:"divisor"`
}
// parityChainSpecAltBnConstOperationPricing defines the price
// policy for bn const operation(used after istanbul)
type parityChainSpecAltBnConstOperationPricing struct {
Price uint64 `json:"price"`
}
// parityChainSepcAltBnPairingPricing defines the price policy
// for bn pairing.
type parityChainSepcAltBnPairingPricing struct {
Base uint64 `json:"base"`
Pair uint64 `json:"pair"`
}
// parityChainSpecBlakePricing defines the price policy for blake2 f
// compression.
type parityChainSpecBlakePricing struct {
GasPerRound uint64 `json:"gas_per_round"`
}
type parityChainSpecAlternativePrice struct {
AltBnConstOperationPrice *parityChainSpecAltBnConstOperationPricing `json:"alt_bn128_const_operations,omitempty"`
AltBnPairingPrice *parityChainSepcAltBnPairingPricing `json:"alt_bn128_pairing,omitempty"`
}
// parityChainSpecVersionedPricing represents a single version price policy.
type parityChainSpecVersionedPricing struct {
Price *parityChainSpecAlternativePrice `json:"price,omitempty"`
Info string `json:"info,omitempty"`
}
// newParityChainSpec converts a go-ethereum genesis block into a Parity specific
// chain specification format.
func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []string) (*parityChainSpec, error) {
// Only ethash is currently supported between go-ethereum and Parity
if genesis.Config.Ethash == nil {
return nil, errors.New("unsupported consensus engine")
}
// Reconstruct the chain spec in Parity's format
spec := &parityChainSpec{
Name: network,
Nodes: bootnodes,
Datadir: strings.ToLower(network),
}
spec.Engine.Ethash.Params.BlockReward = make(map[string]string)
spec.Engine.Ethash.Params.DifficultyBombDelays = make(map[string]string)
// Frontier
spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
spec.Engine.Ethash.Params.BlockReward["0x0"] = hexutil.EncodeBig(ethash.FrontierBlockReward)
// Homestead
spec.Engine.Ethash.Params.HomesteadTransition = hexutil.Uint64(genesis.Config.HomesteadBlock.Uint64())
// Tangerine Whistle : 150
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-608.md
spec.Params.EIP150Transition = hexutil.Uint64(genesis.Config.EIP150Block.Uint64())
// Spurious Dragon: 155, 160, 161, 170
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-607.md
spec.Params.EIP155Transition = hexutil.Uint64(genesis.Config.EIP155Block.Uint64())
spec.Params.EIP160Transition = hexutil.Uint64(genesis.Config.EIP155Block.Uint64())
spec.Params.EIP161abcTransition = hexutil.Uint64(genesis.Config.EIP158Block.Uint64())
spec.Params.EIP161dTransition = hexutil.Uint64(genesis.Config.EIP158Block.Uint64())
// Byzantium
if num := genesis.Config.ByzantiumBlock; num != nil {
spec.setByzantium(num)
}
// Constantinople
if num := genesis.Config.ConstantinopleBlock; num != nil {
spec.setConstantinople(num)
}
// ConstantinopleFix (remove eip-1283)
if num := genesis.Config.PetersburgBlock; num != nil {
spec.setConstantinopleFix(num)
}
// Istanbul
if num := genesis.Config.IstanbulBlock; num != nil {
spec.setIstanbul(num)
}
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
spec.Params.GasLimitBoundDivisor = (math2.HexOrDecimal64)(params.GasLimitBoundDivisor)
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.ChainID = (hexutil.Uint64)(genesis.Config.ChainID.Uint64())
spec.Params.MaxCodeSize = params.MaxCodeSize
// geth has it set from zero
spec.Params.MaxCodeSizeTransition = 0
// Disable this one
spec.Params.EIP98Transition = math.MaxInt64
spec.Genesis.Seal.Ethereum.Nonce = types.EncodeNonce(genesis.Nonce)
spec.Genesis.Seal.Ethereum.MixHash = genesis.Mixhash[:]
spec.Genesis.Difficulty = (*hexutil.Big)(genesis.Difficulty)
spec.Genesis.Author = genesis.Coinbase
spec.Genesis.Timestamp = (hexutil.Uint64)(genesis.Timestamp)
spec.Genesis.ParentHash = genesis.ParentHash
spec.Genesis.ExtraData = genesis.ExtraData
spec.Genesis.GasLimit = (hexutil.Uint64)(genesis.GasLimit)
spec.Accounts = make(map[common.UnprefixedAddress]*parityChainSpecAccount)
for address, account := range genesis.Alloc {
bal := math2.HexOrDecimal256(*account.Balance)
spec.Accounts[common.UnprefixedAddress(address)] = &parityChainSpecAccount{
Balance: bal,
Nonce: math2.HexOrDecimal64(account.Nonce),
}
}
spec.setPrecompile(1, &parityChainSpecBuiltin{Name: "ecrecover",
Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 3000}}})
spec.setPrecompile(2, &parityChainSpecBuiltin{
Name: "sha256", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 60, Word: 12}},
})
spec.setPrecompile(3, &parityChainSpecBuiltin{
Name: "ripemd160", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 600, Word: 120}},
})
spec.setPrecompile(4, &parityChainSpecBuiltin{
Name: "identity", Pricing: &parityChainSpecPricing{Linear: &parityChainSpecLinearPricing{Base: 15, Word: 3}},
})
if genesis.Config.ByzantiumBlock != nil {
spec.setPrecompile(5, &parityChainSpecBuiltin{
Name: "modexp",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: &parityChainSpecPricing{
ModExp: &parityChainSpecModExpPricing{Divisor: 20},
},
})
spec.setPrecompile(6, &parityChainSpecBuiltin{
Name: "alt_bn128_add",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: &parityChainSpecPricing{
Linear: &parityChainSpecLinearPricing{Base: 500, Word: 0},
},
})
spec.setPrecompile(7, &parityChainSpecBuiltin{
Name: "alt_bn128_mul",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: &parityChainSpecPricing{
Linear: &parityChainSpecLinearPricing{Base: 40000, Word: 0},
},
})
spec.setPrecompile(8, &parityChainSpecBuiltin{
Name: "alt_bn128_pairing",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: &parityChainSpecPricing{
AltBnPairing: &parityChainSepcAltBnPairingPricing{Base: 100000, Pair: 80000},
},
})
}
if genesis.Config.IstanbulBlock != nil {
if genesis.Config.ByzantiumBlock == nil {
return nil, errors.New("invalid genesis, istanbul fork is enabled while byzantium is not")
}
spec.setPrecompile(6, &parityChainSpecBuiltin{
Name: "alt_bn128_add",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: map[*hexutil.Big]*parityChainSpecVersionedPricing{
(*hexutil.Big)(big.NewInt(0)): {
Price: &parityChainSpecAlternativePrice{
AltBnConstOperationPrice: &parityChainSpecAltBnConstOperationPricing{Price: 500},
},
},
(*hexutil.Big)(genesis.Config.IstanbulBlock): {
Price: &parityChainSpecAlternativePrice{
AltBnConstOperationPrice: &parityChainSpecAltBnConstOperationPricing{Price: 150},
},
},
},
})
spec.setPrecompile(7, &parityChainSpecBuiltin{
Name: "alt_bn128_mul",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: map[*hexutil.Big]*parityChainSpecVersionedPricing{
(*hexutil.Big)(big.NewInt(0)): {
Price: &parityChainSpecAlternativePrice{
AltBnConstOperationPrice: &parityChainSpecAltBnConstOperationPricing{Price: 40000},
},
},
(*hexutil.Big)(genesis.Config.IstanbulBlock): {
Price: &parityChainSpecAlternativePrice{
AltBnConstOperationPrice: &parityChainSpecAltBnConstOperationPricing{Price: 6000},
},
},
},
})
spec.setPrecompile(8, &parityChainSpecBuiltin{
Name: "alt_bn128_pairing",
ActivateAt: (*hexutil.Big)(genesis.Config.ByzantiumBlock),
Pricing: map[*hexutil.Big]*parityChainSpecVersionedPricing{
(*hexutil.Big)(big.NewInt(0)): {
Price: &parityChainSpecAlternativePrice{
AltBnPairingPrice: &parityChainSepcAltBnPairingPricing{Base: 100000, Pair: 80000},
},
},
(*hexutil.Big)(genesis.Config.IstanbulBlock): {
Price: &parityChainSpecAlternativePrice{
AltBnPairingPrice: &parityChainSepcAltBnPairingPricing{Base: 45000, Pair: 34000},
},
},
},
})
spec.setPrecompile(9, &parityChainSpecBuiltin{
Name: "blake2_f",
ActivateAt: (*hexutil.Big)(genesis.Config.IstanbulBlock),
Pricing: &parityChainSpecPricing{
Blake2F: &parityChainSpecBlakePricing{GasPerRound: 1},
},
})
}
return spec, nil
}
func (spec *parityChainSpec) setPrecompile(address byte, data *parityChainSpecBuiltin) {
if spec.Accounts == nil {
spec.Accounts = make(map[common.UnprefixedAddress]*parityChainSpecAccount)
}
a := common.UnprefixedAddress(common.BytesToAddress([]byte{address}))
if _, exist := spec.Accounts[a]; !exist {
spec.Accounts[a] = &parityChainSpecAccount{}
}
spec.Accounts[a].Builtin = data
}
func (spec *parityChainSpec) setByzantium(num *big.Int) {
spec.Engine.Ethash.Params.BlockReward[hexutil.EncodeBig(num)] = hexutil.EncodeBig(ethash.ByzantiumBlockReward)
spec.Engine.Ethash.Params.DifficultyBombDelays[hexutil.EncodeBig(num)] = hexutil.EncodeUint64(3000000)
n := hexutil.Uint64(num.Uint64())
spec.Engine.Ethash.Params.EIP100bTransition = n
spec.Params.EIP140Transition = n
spec.Params.EIP211Transition = n
spec.Params.EIP214Transition = n
spec.Params.EIP658Transition = n
}
func (spec *parityChainSpec) setConstantinople(num *big.Int) {
spec.Engine.Ethash.Params.BlockReward[hexutil.EncodeBig(num)] = hexutil.EncodeBig(ethash.ConstantinopleBlockReward)
spec.Engine.Ethash.Params.DifficultyBombDelays[hexutil.EncodeBig(num)] = hexutil.EncodeUint64(2000000)
n := hexutil.Uint64(num.Uint64())
spec.Params.EIP145Transition = n
spec.Params.EIP1014Transition = n
spec.Params.EIP1052Transition = n
spec.Params.EIP1283Transition = n
}
func (spec *parityChainSpec) setConstantinopleFix(num *big.Int) {
spec.Params.EIP1283DisableTransition = hexutil.Uint64(num.Uint64())
}
func (spec *parityChainSpec) setIstanbul(num *big.Int) {
spec.Params.EIP1344Transition = hexutil.Uint64(num.Uint64())
spec.Params.EIP1884Transition = hexutil.Uint64(num.Uint64())
spec.Params.EIP2028Transition = hexutil.Uint64(num.Uint64())
spec.Params.EIP1283ReenableTransition = hexutil.Uint64(num.Uint64())
}
// pyEthereumGenesisSpec represents the genesis specification format used by the
// Python Ethereum implementation.
type pyEthereumGenesisSpec struct {
Nonce types.BlockNonce `json:"nonce"`
Timestamp hexutil.Uint64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
Difficulty *hexutil.Big `json:"difficulty"`
Mixhash common.Hash `json:"mixhash"`
Coinbase common.Address `json:"coinbase"`
Alloc core.GenesisAlloc `json:"alloc"`
ParentHash common.Hash `json:"parentHash"`
}
// newPyEthereumGenesisSpec converts a go-ethereum genesis block into a Parity specific
// chain specification format.
func newPyEthereumGenesisSpec(network string, genesis *core.Genesis) (*pyEthereumGenesisSpec, error) {
// Only ethash is currently supported between go-ethereum and pyethereum
if genesis.Config.Ethash == nil {
return nil, errors.New("unsupported consensus engine")
}
spec := &pyEthereumGenesisSpec{
Nonce: types.EncodeNonce(genesis.Nonce),
Timestamp: (hexutil.Uint64)(genesis.Timestamp),
ExtraData: genesis.ExtraData,
GasLimit: (hexutil.Uint64)(genesis.GasLimit),
Difficulty: (*hexutil.Big)(genesis.Difficulty),
Mixhash: genesis.Mixhash,
Coinbase: genesis.Coinbase,
Alloc: genesis.Alloc,
ParentHash: genesis.ParentHash,
}
return spec, nil
}

View file

@ -1,95 +0,0 @@
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"bytes"
"encoding/json"
"os"
"reflect"
"strings"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/core"
)
// Tests the go-ethereum to Aleth chainspec conversion for the Stureby testnet.
func TestAlethSturebyConverter(t *testing.T) {
blob, err := os.ReadFile("testdata/stureby_geth.json")
if err != nil {
t.Fatalf("could not read file: %v", err)
}
var genesis core.Genesis
if err := json.Unmarshal(blob, &genesis); err != nil {
t.Fatalf("failed parsing genesis: %v", err)
}
spec, err := newAlethGenesisSpec("stureby", &genesis)
if err != nil {
t.Fatalf("failed creating chainspec: %v", err)
}
expBlob, err := os.ReadFile("testdata/stureby_aleth.json")
if err != nil {
t.Fatalf("could not read file: %v", err)
}
expspec := &alethGenesisSpec{}
if err := json.Unmarshal(expBlob, expspec); err != nil {
t.Fatalf("failed parsing genesis: %v", err)
}
if !reflect.DeepEqual(expspec, spec) {
t.Errorf("chainspec mismatch")
c := spew.ConfigState{
DisablePointerAddresses: true,
SortKeys: true,
}
exp := strings.Split(c.Sdump(expspec), "\n")
got := strings.Split(c.Sdump(spec), "\n")
for i := 0; i < len(exp) && i < len(got); i++ {
if exp[i] != got[i] {
t.Logf("got: %v\nexp: %v\n", exp[i], got[i])
}
}
}
}
// Tests the go-ethereum to Parity chainspec conversion for the Stureby testnet.
func TestParitySturebyConverter(t *testing.T) {
blob, err := os.ReadFile("testdata/stureby_geth.json")
if err != nil {
t.Fatalf("could not read file: %v", err)
}
var genesis core.Genesis
if err := json.Unmarshal(blob, &genesis); err != nil {
t.Fatalf("failed parsing genesis: %v", err)
}
spec, err := newParityChainSpec("stureby", &genesis, []string{})
if err != nil {
t.Fatalf("failed creating chainspec: %v", err)
}
enc, err := json.MarshalIndent(spec, "", " ")
if err != nil {
t.Fatalf("failed encoding chainspec: %v", err)
}
expBlob, err := os.ReadFile("testdata/stureby_parity.json")
if err != nil {
t.Fatalf("could not read file: %v", err)
}
if !bytes.Equal(expBlob, enc) {
t.Fatalf("chainspec mismatch")
}
}

View file

@ -150,3 +150,12 @@ func checkPort(host string, port int) error {
conn.Close() conn.Close()
return nil return nil
} }
// getEthName gets the Ethereum Name from ethstats
func getEthName(s string) string {
n := strings.Index(s, ":")
if n >= 0 {
return s[:n]
}
return s
}

View file

@ -18,7 +18,6 @@ package main
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"html/template" "html/template"
"math/rand" "math/rand"
@ -582,36 +581,6 @@ func deployDashboard(client *sshClient, network string, conf *config, config *da
// Marshal the genesis spec files for go-ethereum and all the other clients // Marshal the genesis spec files for go-ethereum and all the other clients
genesis, _ := conf.Genesis.MarshalJSON() genesis, _ := conf.Genesis.MarshalJSON()
files[filepath.Join(workdir, network+".json")] = genesis files[filepath.Join(workdir, network+".json")] = genesis
if conf.Genesis.Config.Ethash != nil {
cppSpec, err := newAlethGenesisSpec(network, conf.Genesis)
if err != nil {
return nil, err
}
cppSpecJSON, _ := json.Marshal(cppSpec)
files[filepath.Join(workdir, network+"-cpp.json")] = cppSpecJSON
harmonySpecJSON, _ := conf.Genesis.MarshalJSON()
files[filepath.Join(workdir, network+"-harmony.json")] = harmonySpecJSON
paritySpec, err := newParityChainSpec(network, conf.Genesis, conf.bootnodes)
if err != nil {
return nil, err
}
paritySpecJSON, _ := json.Marshal(paritySpec)
files[filepath.Join(workdir, network+"-parity.json")] = paritySpecJSON
pyethSpec, err := newPyEthereumGenesisSpec(network, conf.Genesis)
if err != nil {
return nil, err
}
pyethSpecJSON, _ := json.Marshal(pyethSpec)
files[filepath.Join(workdir, network+"-python.json")] = pyethSpecJSON
} else {
for _, client := range []string{"cpp", "harmony", "parity", "python"} {
files[filepath.Join(workdir, network+"-"+client+".json")] = []byte{}
}
}
files[filepath.Join(workdir, "puppeth.png")] = dashboardMascot files[filepath.Join(workdir, "puppeth.png")] = dashboardMascot
// Upload the deployment files to the remote server (and clean up afterwards) // Upload the deployment files to the remote server (and clean up afterwards)

View file

@ -104,7 +104,7 @@ func deployExplorer(client *sshClient, network string, bootnodes []string, confi
"Datadir": config.node.datadir, "Datadir": config.node.datadir,
"DBDir": config.dbdir, "DBDir": config.dbdir,
"EthPort": config.node.port, "EthPort": config.node.port,
"EthName": config.node.ethstats[:strings.Index(config.node.ethstats, ":")], "EthName": getEthName(config.node.ethstats),
"WebPort": config.port, "WebPort": config.port,
"Transformer": transformer, "Transformer": transformer,
}) })

View file

@ -116,7 +116,7 @@ func deployFaucet(client *sshClient, network string, bootnodes []string, config
"VHost": config.host, "VHost": config.host,
"ApiPort": config.port, "ApiPort": config.port,
"EthPort": config.node.port, "EthPort": config.node.port,
"EthName": config.node.ethstats[:strings.Index(config.node.ethstats, ":")], "EthName": getEthName(config.node.ethstats),
"CaptchaToken": config.captchaToken, "CaptchaToken": config.captchaToken,
"CaptchaSecret": config.captchaSecret, "CaptchaSecret": config.captchaSecret,
"FaucetAmount": config.amount, "FaucetAmount": config.amount,

View file

@ -123,7 +123,7 @@ func deployNode(client *sshClient, network string, bootnodes []string, config *n
"TotalPeers": config.peersTotal, "TotalPeers": config.peersTotal,
"Light": config.peersLight > 0, "Light": config.peersLight > 0,
"LightPeers": config.peersLight, "LightPeers": config.peersLight,
"Ethstats": config.ethstats[:strings.Index(config.ethstats, ":")], "Ethstats": getEthName(config.ethstats),
"Etherbase": config.etherbase, "Etherbase": config.etherbase,
"GasTarget": config.gasTarget, "GasTarget": config.gasTarget,
"GasLimit": config.gasLimit, "GasLimit": config.gasLimit,

View file

@ -163,7 +163,7 @@ func dial(server string, pubkey []byte) (*sshClient, error) {
return nil return nil
} }
// We have a mismatch, forbid connecting // We have a mismatch, forbid connecting
return errors.New("ssh key mismatch, readd the machine to update") return errors.New("ssh key mismatch, re-add the machine to update")
} }
client, err := ssh.Dial("tcp", hostport, &ssh.ClientConfig{User: username, Auth: auths, HostKeyCallback: keycheck}) client, err := ssh.Dial("tcp", hostport, &ssh.ClientConfig{User: username, Auth: auths, HostKeyCallback: keycheck})
if err != nil { if err != nil {

View file

@ -250,8 +250,8 @@ func (w *wizard) manageGenesis() {
case "2": case "2":
// Save whatever genesis configuration we currently have // Save whatever genesis configuration we currently have
fmt.Println() fmt.Println()
fmt.Printf("Which folder to save the genesis specs into? (default = current)\n") fmt.Printf("Which folder to save the genesis spec into? (default = current)\n")
fmt.Printf(" Will create %s.json, %s-aleth.json, %s-harmony.json, %s-parity.json\n", w.network, w.network, w.network, w.network) fmt.Printf(" Will create %s.json\n", w.network)
folder := w.readDefaultString(".") folder := w.readDefaultString(".")
if err := os.MkdirAll(folder, 0755); err != nil { if err := os.MkdirAll(folder, 0755); err != nil {
@ -268,21 +268,6 @@ func (w *wizard) manageGenesis() {
} }
log.Info("Saved native genesis chain spec", "path", gethJson) log.Info("Saved native genesis chain spec", "path", gethJson)
// Export the genesis spec used by Aleth (formerly C++ Ethereum)
if spec, err := newAlethGenesisSpec(w.network, w.conf.Genesis); err != nil {
log.Error("Failed to create Aleth chain spec", "err", err)
} else {
saveGenesis(folder, w.network, "aleth", spec)
}
// Export the genesis spec used by Parity
if spec, err := newParityChainSpec(w.network, w.conf.Genesis, []string{}); err != nil {
log.Error("Failed to create Parity chain spec", "err", err)
} else {
saveGenesis(folder, w.network, "parity", spec)
}
// Export the genesis spec used by Harmony (formerly EthereumJ)
saveGenesis(folder, w.network, "harmony", w.conf.Genesis)
case "3": case "3":
// Make sure we don't have any services running // Make sure we don't have any services running
if len(w.conf.servers()) > 0 { if len(w.conf.servers()) > 0 {
@ -298,15 +283,3 @@ func (w *wizard) manageGenesis() {
return return
} }
} }
// saveGenesis JSON encodes an arbitrary genesis spec into a pre-defined file.
func saveGenesis(folder, network, client string, spec interface{}) {
path := filepath.Join(folder, fmt.Sprintf("%s-%s.json", network, client))
out, _ := json.MarshalIndent(spec, "", " ")
if err := os.WriteFile(path, out, 0644); err != nil {
log.Error("Failed to save genesis file", "client", client, "err", err)
return
}
log.Info("Saved genesis chain spec", "client", client, "path", path)
}

View file

@ -33,7 +33,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/fdlimit" "github.com/ethereum/go-ethereum/common/fdlimit"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
@ -43,6 +42,7 @@ import (
ethcatalyst "github.com/ethereum/go-ethereum/eth/catalyst" ethcatalyst "github.com/ethereum/go-ethereum/eth/catalyst"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -64,6 +64,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/nat" "github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/p2p/netutil" "github.com/ethereum/go-ethereum/p2p/netutil"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
pcsclite "github.com/gballet/go-libpcsclite" pcsclite "github.com/gballet/go-libpcsclite"
gopsutil "github.com/shirou/gopsutil/mem" gopsutil "github.com/shirou/gopsutil/mem"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
@ -91,7 +92,7 @@ var (
} }
AncientFlag = &flags.DirectoryFlag{ AncientFlag = &flags.DirectoryFlag{
Name: "datadir.ancient", Name: "datadir.ancient",
Usage: "Data directory for ancient chain segments (default = inside chaindata)", Usage: "Root directory for ancient data (default = inside chaindata)",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
MinFreeDiskSpaceFlag = &flags.DirectoryFlag{ MinFreeDiskSpaceFlag = &flags.DirectoryFlag{
@ -262,17 +263,16 @@ var (
Value: 2048, Value: 2048,
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideGrayGlacierFlag = &cli.Uint64Flag{
Name: "override.grayglacier",
Usage: "Manually specify Gray Glacier fork-block, overriding the bundled setting",
Category: flags.EthCategory,
}
OverrideTerminalTotalDifficulty = &flags.BigFlag{ OverrideTerminalTotalDifficulty = &flags.BigFlag{
Name: "override.terminaltotaldifficulty", Name: "override.terminaltotaldifficulty",
Usage: "Manually specify TerminalTotalDifficulty, overriding the bundled setting", Usage: "Manually specify TerminalTotalDifficulty, overriding the bundled setting",
Category: flags.EthCategory, Category: flags.EthCategory,
} }
OverrideTerminalTotalDifficultyPassed = &cli.BoolFlag{
Name: "override.terminaltotaldifficultypassed",
Usage: "Manually specify TerminalTotalDifficultyPassed, overriding the bundled setting",
Category: flags.EthCategory,
}
// Light server and client settings // Light server and client settings
LightServeFlag = &cli.IntFlag{ LightServeFlag = &cli.IntFlag{
Name: "light.serve", Name: "light.serve",
@ -492,6 +492,12 @@ var (
Usage: "Enable recording the SHA3/keccak preimages of trie keys", Usage: "Enable recording the SHA3/keccak preimages of trie keys",
Category: flags.PerfCategory, Category: flags.PerfCategory,
} }
CacheLogSizeFlag = &cli.IntFlag{
Name: "cache.blocklogs",
Usage: "Size (in number of blocks) of the log cache for filtering",
Category: flags.PerfCategory,
Value: ethconfig.Defaults.FilterLogCacheSize,
}
FDLimitFlag = &cli.IntFlag{ FDLimitFlag = &cli.IntFlag{
Name: "fdlimit", Name: "fdlimit",
Usage: "Raise the open file descriptor resource limit (default = system fd limit)", Usage: "Raise the open file descriptor resource limit (default = system fd limit)",
@ -994,15 +1000,6 @@ var (
} }
) )
// GroupFlags combines the given flag slices together and returns the merged one.
func GroupFlags(groups ...[]cli.Flag) []cli.Flag {
var ret []cli.Flag
for _, group := range groups {
ret = append(ret, group...)
}
return ret
}
// MakeDataDir retrieves the currently requested data directory, terminating // MakeDataDir retrieves the currently requested data directory, terminating
// if none (or the empty string) is specified. If the node is starting a testnet, // if none (or the empty string) is specified. If the node is starting a testnet,
// then a subdirectory of the specified datadir will be used. // then a subdirectory of the specified datadir will be used.
@ -1818,6 +1815,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) { if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100 cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
} }
if ctx.IsSet(CacheLogSizeFlag.Name) {
cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
}
if !ctx.Bool(SnapshotFlag.Name) { if !ctx.Bool(SnapshotFlag.Name) {
// If snap-sync is requested, this flag is also required // If snap-sync is requested, this flag is also required
if cfg.SyncMode == downloader.SnapSync { if cfg.SyncMode == downloader.SnapSync {
@ -1993,10 +1993,8 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
Fatalf("Failed to register the Ethereum service: %v", err) Fatalf("Failed to register the Ethereum service: %v", err)
} }
stack.RegisterAPIs(tracers.APIs(backend.ApiBackend)) stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
if backend.BlockChain().Config().TerminalTotalDifficulty != nil {
if err := lescatalyst.Register(stack, backend); err != nil { if err := lescatalyst.Register(stack, backend); err != nil {
Fatalf("Failed to register the catalyst service: %v", err) Fatalf("Failed to register the Engine API service: %v", err)
}
} }
return backend.ApiBackend, nil return backend.ApiBackend, nil
} }
@ -2010,30 +2008,41 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
Fatalf("Failed to create the LES server: %v", err) Fatalf("Failed to create the LES server: %v", err)
} }
} }
if backend.BlockChain().Config().TerminalTotalDifficulty != nil {
if err := ethcatalyst.Register(stack, backend); err != nil { if err := ethcatalyst.Register(stack, backend); err != nil {
Fatalf("Failed to register the catalyst service: %v", err) Fatalf("Failed to register the Engine API service: %v", err)
}
} }
stack.RegisterAPIs(tracers.APIs(backend.APIBackend)) stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
return backend.APIBackend, backend return backend.APIBackend, backend
} }
// RegisterEthStatsService configures the Ethereum Stats daemon and adds it to // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
// the given node.
func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) { func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) {
if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil { if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
Fatalf("Failed to register the Ethereum Stats service: %v", err) Fatalf("Failed to register the Ethereum Stats service: %v", err)
} }
} }
// RegisterGraphQLService is a utility function to construct a new service and register it against a node. // RegisterGraphQLService adds the GraphQL API to the node.
func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, cfg node.Config) { func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cfg *node.Config) {
if err := graphql.New(stack, backend, cfg.GraphQLCors, cfg.GraphQLVirtualHosts); err != nil { err := graphql.New(stack, backend, filterSystem, cfg.GraphQLCors, cfg.GraphQLVirtualHosts)
if err != nil {
Fatalf("Failed to register the GraphQL service: %v", err) Fatalf("Failed to register the GraphQL service: %v", err)
} }
} }
// RegisterFilterAPI adds the eth log filtering RPC API to the node.
func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
isLightClient := ethcfg.SyncMode == downloader.LightSync
filterSystem := filters.NewFilterSystem(backend, filters.Config{
LogCacheSize: ethcfg.FilterLogCacheSize,
})
stack.RegisterAPIs([]rpc.API{{
Namespace: "eth",
Service: filters.NewFilterAPI(filterSystem, isLightClient),
}})
return filterSystem
}
func SetupMetrics(ctx *cli.Context) { func SetupMetrics(ctx *cli.Context) {
if metrics.Enabled { if metrics.Enabled {
log.Info("Enabling metrics collection") log.Info("Enabling metrics collection")
@ -2156,20 +2165,20 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
} }
// MakeChain creates a chain manager from set command line flags. // MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { func MakeChain(ctx *cli.Context, stack *node.Node) (*core.BlockChain, ethdb.Database) {
var err error var (
gspec = MakeGenesis(ctx)
chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database
config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) )
cliqueConfig, err := core.LoadCliqueConfig(chainDb, gspec)
if err != nil { if err != nil {
Fatalf("%v", err) Fatalf("%v", err)
} }
ethashConfig := ethconfig.Defaults.Ethash
var engine consensus.Engine
ethashConf := ethconfig.Defaults.Ethash
if ctx.Bool(FakePoWFlag.Name) { if ctx.Bool(FakePoWFlag.Name) {
ethashConf.PowMode = ethash.ModeFake ethashConfig.PowMode = ethash.ModeFake
} }
engine = ethconfig.CreateConsensusEngine(stack, config, &ethashConf, nil, false, chainDb) engine := ethconfig.CreateConsensusEngine(stack, &ethashConfig, cliqueConfig, nil, false, chainDb)
if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
} }
@ -2199,7 +2208,7 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
// TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only. // TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
// Disable transaction indexing/unindexing by default. // Disable transaction indexing/unindexing by default.
chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil) chain, err := core.NewBlockChain(chainDb, cache, gspec, nil, engine, vmcfg, nil, nil)
if err != nil { if err != nil {
Fatalf("Can't create BlockChain: %v", err) Fatalf("Can't create BlockChain: %v", err)
} }

View file

@ -66,13 +66,16 @@ func ParseCombinedJSON(combinedJSON []byte, source string, languageVersion strin
contracts := make(map[string]*Contract) contracts := make(map[string]*Contract)
for name, info := range output.Contracts { for name, info := range output.Contracts {
// Parse the individual compilation results. // Parse the individual compilation results.
var abi interface{} var abi, userdoc, devdoc interface{}
if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil { if err := json.Unmarshal([]byte(info.Abi), &abi); err != nil {
return nil, fmt.Errorf("solc: error reading abi definition (%v)", err) return nil, fmt.Errorf("solc: error reading abi definition (%v)", err)
} }
var userdoc, devdoc interface{} if err := json.Unmarshal([]byte(info.Userdoc), &userdoc); err != nil {
json.Unmarshal([]byte(info.Userdoc), &userdoc) return nil, fmt.Errorf("solc: error reading userdoc definition (%v)", err)
json.Unmarshal([]byte(info.Devdoc), &devdoc) }
if err := json.Unmarshal([]byte(info.Devdoc), &devdoc); err != nil {
return nil, fmt.Errorf("solc: error reading devdoc definition (%v)", err)
}
contracts[name] = &Contract{ contracts[name] = &Contract{
Code: "0x" + info.Bin, Code: "0x" + info.Bin,

View file

@ -171,7 +171,6 @@ func BenchmarkByteAt(b *testing.B) {
} }
func BenchmarkByteAtOld(b *testing.B) { func BenchmarkByteAtOld(b *testing.B) {
bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC") bigint := MustParseBig256("0x18F8F8F1000111000110011100222004330052300000000000000000FEFCF3CC")
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
PaddedBigBytes(bigint, 32) PaddedBigBytes(bigint, 32)
@ -244,7 +243,6 @@ func TestBigEndianByteAt(t *testing.T) {
if actual != test.exp { if actual != test.exp {
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
} }
} }
} }
func TestLittleEndianByteAt(t *testing.T) { func TestLittleEndianByteAt(t *testing.T) {
@ -277,7 +275,6 @@ func TestLittleEndianByteAt(t *testing.T) {
if actual != test.exp { if actual != test.exp {
t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual) t.Fatalf("Expected [%v] %v:th byte to be %v, was %v.", test.x, test.y, test.exp, actual)
} }
} }
} }

View file

@ -58,7 +58,7 @@ func (s *Simulated) Run(d time.Duration) {
s.mu.Lock() s.mu.Lock()
s.init() s.init()
end := s.now + AbsTime(d) end := s.now.Add(d)
var do []func() var do []func()
for len(s.scheduled) > 0 && s.scheduled[0].at <= end { for len(s.scheduled) > 0 && s.scheduled[0].at <= end {
ev := heap.Pop(&s.scheduled).(*simTimer) ev := heap.Pop(&s.scheduled).(*simTimer)
@ -134,7 +134,7 @@ func (s *Simulated) AfterFunc(d time.Duration, fn func()) Timer {
func (s *Simulated) schedule(d time.Duration, fn func()) *simTimer { func (s *Simulated) schedule(d time.Duration, fn func()) *simTimer {
s.init() s.init()
at := s.now + AbsTime(d) at := s.now.Add(d)
ev := &simTimer{do: fn, at: at, s: s} ev := &simTimer{do: fn, at: at, s: s}
heap.Push(&s.scheduled, ev) heap.Push(&s.scheduled, ev)
s.cond.Broadcast() s.cond.Broadcast()

View file

@ -87,13 +87,13 @@ func (q *LazyQueue) Refresh() {
// refresh re-evaluates items in the older queue and swaps the two queues // refresh re-evaluates items in the older queue and swaps the two queues
func (q *LazyQueue) refresh(now mclock.AbsTime) { func (q *LazyQueue) refresh(now mclock.AbsTime) {
q.maxUntil = now + mclock.AbsTime(q.period) q.maxUntil = now.Add(q.period)
for q.queue[0].Len() != 0 { for q.queue[0].Len() != 0 {
q.Push(heap.Pop(q.queue[0]).(*item).value) q.Push(heap.Pop(q.queue[0]).(*item).value)
} }
q.queue[0], q.queue[1] = q.queue[1], q.queue[0] q.queue[0], q.queue[1] = q.queue[1], q.queue[0]
q.indexOffset = 1 - q.indexOffset q.indexOffset = 1 - q.indexOffset
q.maxUntil += mclock.AbsTime(q.period) q.maxUntil = q.maxUntil.Add(q.period)
} }
// Push adds an item to the queue // Push adds an item to the queue

View file

@ -41,13 +41,13 @@ func (p *Prque) Push(data interface{}, priority int64) {
heap.Push(p.cont, &item{data, priority}) heap.Push(p.cont, &item{data, priority})
} }
// Peek returns the value with the greates priority but does not pop it off. // Peek returns the value with the greatest priority but does not pop it off.
func (p *Prque) Peek() (interface{}, int64) { func (p *Prque) Peek() (interface{}, int64) {
item := p.cont.blocks[0][0] item := p.cont.blocks[0][0]
return item.value, item.priority return item.value, item.priority
} }
// Pops the value with the greates priority off the stack and returns it. // Pops the value with the greatest priority off the stack and returns it.
// Currently no shrinking is done. // Currently no shrinking is done.
func (p *Prque) Pop() (interface{}, int64) { func (p *Prque) Pop() (interface{}, int64) {
item := heap.Pop(p.cont).(*item) item := heap.Pop(p.cont).(*item)

View file

@ -155,7 +155,6 @@ func BenchmarkAddressHex(b *testing.B) {
} }
func TestMixedcaseAccount_Address(t *testing.T) { func TestMixedcaseAccount_Address(t *testing.T) {
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md
// Note: 0X{checksum_addr} is not valid according to spec above // Note: 0X{checksum_addr} is not valid according to spec above
@ -192,9 +191,7 @@ func TestMixedcaseAccount_Address(t *testing.T) {
if err := json.Unmarshal([]byte(r), &r2); err == nil { if err := json.Unmarshal([]byte(r), &r2); err == nil {
t.Errorf("Expected failure, input %v", r) t.Errorf("Expected failure, input %v", r)
} }
} }
} }
func TestHash_Scan(t *testing.T) { func TestHash_Scan(t *testing.T) {

View file

@ -79,7 +79,10 @@ func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
// VerifyHeader checks whether a header conforms to the consensus rules of the // VerifyHeader checks whether a header conforms to the consensus rules of the
// stock Ethereum consensus engine. // stock Ethereum consensus engine.
func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error { func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *types.Header, seal bool) error {
reached, _ := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1) reached, err := IsTTDReached(chain, header.ParentHash, header.Number.Uint64()-1)
if err != nil {
return err
}
if !reached { if !reached {
return beacon.ethone.VerifyHeader(chain, header, seal) return beacon.ethone.VerifyHeader(chain, header, seal)
} }
@ -114,8 +117,19 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
} }
} }
// All the headers have passed the transition point, use new rules.
if len(preHeaders) == 0 { if len(preHeaders) == 0 {
// All the headers are pos headers. Verify that the parent block reached total terminal difficulty.
if reached, err := IsTTDReached(chain, headers[0].ParentHash, headers[0].Number.Uint64()-1); !reached {
// TTD not reached for the first block, mark subsequent with invalid terminal block
if err == nil {
err = consensus.ErrInvalidTerminalBlock
}
results := make(chan error, len(headers))
for i := 0; i < len(headers); i++ {
results <- err
}
return make(chan struct{}), results
}
return beacon.verifyHeaders(chain, headers, nil) return beacon.verifyHeaders(chain, headers, nil)
} }
@ -167,7 +181,7 @@ func (beacon *Beacon) VerifyHeaders(chain consensus.ChainHeaderReader, headers [
return abort, results return abort, results
} }
// verifyTerminalPoWBlock verifies that the preHeaders confirm to the specification // verifyTerminalPoWBlock verifies that the preHeaders conform to the specification
// wrt. their total difficulty. // wrt. their total difficulty.
// It expects: // It expects:
// - preHeaders to be at least 1 element // - preHeaders to be at least 1 element

View file

@ -45,6 +45,7 @@ func TestReimportMirroredState(t *testing.T) {
signer = new(types.HomesteadSigner) signer = new(types.HomesteadSigner)
) )
genspec := &core.Genesis{ genspec := &core.Genesis{
Config: params.AllCliqueProtocolChanges,
ExtraData: make([]byte, extraVanity+common.AddressLength+extraSeal), ExtraData: make([]byte, extraVanity+common.AddressLength+extraSeal),
Alloc: map[common.Address]core.GenesisAccount{ Alloc: map[common.Address]core.GenesisAccount{
addr: {Balance: big.NewInt(10000000000000000)}, addr: {Balance: big.NewInt(10000000000000000)},
@ -55,7 +56,7 @@ func TestReimportMirroredState(t *testing.T) {
genesis := genspec.MustCommit(db) genesis := genspec.MustCommit(db)
// Generate a batch of blocks, each properly signed // Generate a batch of blocks, each properly signed
chain, _ := core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil) chain, _ := core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
blocks, _ := core.GenerateChain(params.AllCliqueProtocolChanges, genesis, engine, db, 3, func(i int, block *core.BlockGen) { blocks, _ := core.GenerateChain(params.AllCliqueProtocolChanges, genesis, engine, db, 3, func(i int, block *core.BlockGen) {
@ -89,7 +90,7 @@ func TestReimportMirroredState(t *testing.T) {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
genspec.MustCommit(db) genspec.MustCommit(db)
chain, _ = core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil) chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
if _, err := chain.InsertChain(blocks[:2]); err != nil { if _, err := chain.InsertChain(blocks[:2]); err != nil {
@ -102,7 +103,7 @@ func TestReimportMirroredState(t *testing.T) {
// Simulate a crash by creating a new chain on top of the database, without // Simulate a crash by creating a new chain on top of the database, without
// flushing the dirty states out. Insert the last block, triggering a sidechain // flushing the dirty states out. Insert the last block, triggering a sidechain
// reimport. // reimport.
chain, _ = core.NewBlockChain(db, nil, params.AllCliqueProtocolChanges, engine, vm.Config{}, nil, nil) chain, _ = core.NewBlockChain(db, nil, genspec, nil, engine, vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
if _, err := chain.InsertChain(blocks[2:]); err != nil { if _, err := chain.InsertChain(blocks[2:]); err != nil {

View file

@ -305,7 +305,7 @@ func TestClique(t *testing.T) {
}, { }, {
// Ensure that pending votes don't survive authorization status changes. This // Ensure that pending votes don't survive authorization status changes. This
// corner case can only appear if a signer is quickly added, removed and then // corner case can only appear if a signer is quickly added, removed and then
// readded (or the inverse), while one of the original voters dropped. If a // re-added (or the inverse), while one of the original voters dropped. If a
// past vote is left cached in the system somewhere, this will interfere with // past vote is left cached in the system somewhere, this will interfere with
// the final signer outcome. // the final signer outcome.
signers: []string{"A", "B", "C", "D", "E"}, signers: []string{"A", "B", "C", "D", "E"},
@ -344,7 +344,7 @@ func TestClique(t *testing.T) {
}, },
failure: errUnauthorizedSigner, failure: errUnauthorizedSigner,
}, { }, {
// An authorized signer that signed recenty should not be able to sign again // An authorized signer that signed recently should not be able to sign again
signers: []string{"A", "B"}, signers: []string{"A", "B"},
votes: []testerVote{ votes: []testerVote{
{signer: "A"}, {signer: "A"},
@ -403,7 +403,7 @@ func TestClique(t *testing.T) {
} }
// Create a pristine blockchain with the genesis injected // Create a pristine blockchain with the genesis injected
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis.Commit(db) genesisBlock := genesis.MustCommit(db)
// Assemble a chain of headers from the cast votes // Assemble a chain of headers from the cast votes
config := *params.TestChainConfig config := *params.TestChainConfig
@ -411,10 +411,11 @@ func TestClique(t *testing.T) {
Period: 1, Period: 1,
Epoch: tt.epoch, Epoch: tt.epoch,
} }
genesis.Config = &config
engine := New(config.Clique, db) engine := New(config.Clique, db)
engine.fakeDiff = true engine.fakeDiff = true
blocks, _ := core.GenerateChain(&config, genesis.ToBlock(db), engine, db, len(tt.votes), func(j int, gen *core.BlockGen) { blocks, _ := core.GenerateChain(&config, genesisBlock, engine, db, len(tt.votes), func(j int, gen *core.BlockGen) {
// Cast the vote contained in this block // Cast the vote contained in this block
gen.SetCoinbase(accounts.address(tt.votes[j].voted)) gen.SetCoinbase(accounts.address(tt.votes[j].voted))
if tt.votes[j].auth { if tt.votes[j].auth {
@ -450,7 +451,7 @@ func TestClique(t *testing.T) {
batches[len(batches)-1] = append(batches[len(batches)-1], block) batches[len(batches)-1] = append(batches[len(batches)-1], block)
} }
// Pass all the headers through clique and ensure tallying succeeds // Pass all the headers through clique and ensure tallying succeeds
chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil, nil) chain, err := core.NewBlockChain(db, nil, genesis, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Errorf("test %d: failed to create test chain: %v", i, err) t.Errorf("test %d: failed to create test chain: %v", i, err)
continue continue

View file

@ -278,8 +278,11 @@ func (c *cache) generate(dir string, limit int, lock bool, test bool) {
// Iterate over all previous instances and delete old ones // Iterate over all previous instances and delete old ones
for ep := int(c.epoch) - limit; ep >= 0; ep-- { for ep := int(c.epoch) - limit; ep >= 0; ep-- {
seed := seedHash(uint64(ep)*epochLength + 1) seed := seedHash(uint64(ep)*epochLength + 1)
path := filepath.Join(dir, fmt.Sprintf("cache-R%d-%x%s", algorithmRevision, seed[:8], endian)) path := filepath.Join(dir, fmt.Sprintf("cache-R%d-%x%s*", algorithmRevision, seed[:8], endian))
os.Remove(path) files, _ := filepath.Glob(path) // find also the temp files that are generated.
for _, file := range files {
os.Remove(file)
}
} }
}) })
} }

View file

@ -290,7 +290,7 @@ func (c *Console) AutoCompleteInput(line string, pos int) (string, []string, str
if len(line) == 0 || pos == 0 { if len(line) == 0 || pos == 0 {
return "", nil, "" return "", nil, ""
} }
// Chunck data to relevant part for autocompletion // Chunk data to relevant part for autocompletion
// E.g. in case of nested lines eth.getBalance(eth.coinb<tab><tab> // E.g. in case of nested lines eth.getBalance(eth.coinb<tab><tab>
start := pos - 1 start := pos - 1
for ; start > 0; start-- { for ; start > 0; start-- {
@ -407,7 +407,7 @@ func (c *Console) StopInteractive() {
} }
} }
// Interactive starts an interactive user session, where in.put is propted from // Interactive starts an interactive user session, where input is prompted from
// the configured user prompter. // the configured user prompter.
func (c *Console) Interactive() { func (c *Console) Interactive() {
var ( var (
@ -497,7 +497,7 @@ func (c *Console) readLines(input chan<- string, errc chan<- error, prompt <-cha
} }
} }
// countIndents returns the number of identations for the given input. // countIndents returns the number of indentations for the given input.
// In case of invalid input such as var a = } the result can be negative. // In case of invalid input such as var a = } the result can be negative.
func countIndents(input string) int { func countIndents(input string) int {
var ( var (

View file

@ -42,7 +42,7 @@ type payloadAttributesMarshaling struct {
//go:generate go run github.com/fjl/gencodec -type ExecutableDataV1 -field-override executableDataMarshaling -out gen_ed.go //go:generate go run github.com/fjl/gencodec -type ExecutableDataV1 -field-override executableDataMarshaling -out gen_ed.go
// ExecutableDataV1 structure described at https://github.com/ethereum/execution-apis/src/engine/specification.md // ExecutableDataV1 structure described at https://github.com/ethereum/execution-apis/tree/main/src/engine/specification.md
type ExecutableDataV1 struct { type ExecutableDataV1 struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"` ParentHash common.Hash `json:"parentHash" gencodec:"required"`
FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"` FeeRecipient common.Address `json:"feeRecipient" gencodec:"required"`

View file

@ -196,7 +196,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Time the insertion of the new chain. // Time the insertion of the new chain.
// State and blocks are stored in the same DB. // State and blocks are stored in the same DB.
chainman, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) chainman, _ := NewBlockChain(db, nil, &gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer chainman.Stop() defer chainman.Stop()
b.ReportAllocs() b.ReportAllocs()
b.ResetTimer() b.ResetTimer()
@ -262,6 +262,11 @@ func makeChainForBench(db ethdb.Database, full bool, count uint64) {
rawdb.WriteCanonicalHash(db, hash, n) rawdb.WriteCanonicalHash(db, hash, n)
rawdb.WriteTd(db, hash, n, big.NewInt(int64(n+1))) rawdb.WriteTd(db, hash, n, big.NewInt(int64(n+1)))
if n == 0 {
rawdb.WriteChainConfig(db, hash, params.AllEthashProtocolChanges)
}
rawdb.WriteHeadHeaderHash(db, hash)
if full || n == 0 { if full || n == 0 {
block := types.NewBlockWithHeader(header) block := types.NewBlockWithHeader(header)
rawdb.WriteBody(db, hash, n, block.Body()) rawdb.WriteBody(db, hash, n, block.Body())
@ -303,7 +308,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
if err != nil { if err != nil {
b.Fatalf("error opening database at %v: %v", dir, err) b.Fatalf("error opening database at %v: %v", dir, err)
} }
chain, err := NewBlockChain(db, &cacheConfig, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) chain, err := NewBlockChain(db, &cacheConfig, nil, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil { if err != nil {
b.Fatalf("error creating chain: %v", err) b.Fatalf("error creating chain: %v", err)
} }

View file

@ -49,7 +49,7 @@ func TestHeaderVerification(t *testing.T) {
headers[i] = block.Header() headers[i] = block.Header()
} }
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) chain, _ := NewBlockChain(testdb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
for i := 0; i < len(blocks); i++ { for i := 0; i < len(blocks); i++ {
@ -93,7 +93,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
preBlocks []*types.Block preBlocks []*types.Block
postBlocks []*types.Block postBlocks []*types.Block
runEngine consensus.Engine runEngine consensus.Engine
chainConfig *params.ChainConfig genspec *Genesis
merger = consensus.NewMerger(rawdb.NewMemoryDatabase()) merger = consensus.NewMerger(rawdb.NewMemoryDatabase())
) )
if isClique { if isClique {
@ -102,7 +102,8 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
addr = crypto.PubkeyToAddress(key.PublicKey) addr = crypto.PubkeyToAddress(key.PublicKey)
engine = clique.New(params.AllCliqueProtocolChanges.Clique, testdb) engine = clique.New(params.AllCliqueProtocolChanges.Clique, testdb)
) )
genspec := &Genesis{ genspec = &Genesis{
Config: params.AllCliqueProtocolChanges,
ExtraData: make([]byte, 32+common.AddressLength+crypto.SignatureLength), ExtraData: make([]byte, 32+common.AddressLength+crypto.SignatureLength),
Alloc: map[common.Address]GenesisAccount{ Alloc: map[common.Address]GenesisAccount{
addr: {Balance: big.NewInt(1)}, addr: {Balance: big.NewInt(1)},
@ -133,11 +134,11 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
config := *params.AllCliqueProtocolChanges config := *params.AllCliqueProtocolChanges
config.TerminalTotalDifficulty = big.NewInt(int64(td)) config.TerminalTotalDifficulty = big.NewInt(int64(td))
postBlocks, _ = GenerateChain(&config, preBlocks[len(preBlocks)-1], genEngine, testdb, 8, nil) postBlocks, _ = GenerateChain(&config, preBlocks[len(preBlocks)-1], genEngine, testdb, 8, nil)
chainConfig = &config
runEngine = beacon.New(engine) runEngine = beacon.New(engine)
genspec.Config = &config
} else { } else {
gspec := &Genesis{Config: params.TestChainConfig} genspec = &Genesis{Config: params.TestChainConfig}
genesis := gspec.MustCommit(testdb) genesis := genspec.MustCommit(testdb)
genEngine := beacon.New(ethash.NewFaker()) genEngine := beacon.New(ethash.NewFaker())
preBlocks, _ = GenerateChain(params.TestChainConfig, genesis, genEngine, testdb, 8, nil) preBlocks, _ = GenerateChain(params.TestChainConfig, genesis, genEngine, testdb, 8, nil)
@ -150,8 +151,8 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
config.TerminalTotalDifficulty = big.NewInt(int64(td)) config.TerminalTotalDifficulty = big.NewInt(int64(td))
postBlocks, _ = GenerateChain(params.TestChainConfig, preBlocks[len(preBlocks)-1], genEngine, testdb, 8, nil) postBlocks, _ = GenerateChain(params.TestChainConfig, preBlocks[len(preBlocks)-1], genEngine, testdb, 8, nil)
chainConfig = &config
runEngine = beacon.New(ethash.NewFaker()) runEngine = beacon.New(ethash.NewFaker())
genspec.Config = &config
} }
preHeaders := make([]*types.Header, len(preBlocks)) preHeaders := make([]*types.Header, len(preBlocks))
@ -169,7 +170,7 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
t.Logf("Log header after the merging %d: %v", block.NumberU64(), string(blob)) t.Logf("Log header after the merging %d: %v", block.NumberU64(), string(blob))
} }
// Run the header checker for blocks one-by-one, checking for both valid and invalid nonces // Run the header checker for blocks one-by-one, checking for both valid and invalid nonces
chain, _ := NewBlockChain(testdb, nil, chainConfig, runEngine, vm.Config{}, nil, nil) chain, _ := NewBlockChain(testdb, nil, genspec, nil, runEngine, vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
// Verify the blocks before the merging // Verify the blocks before the merging
@ -280,11 +281,11 @@ func testHeaderConcurrentVerification(t *testing.T, threads int) {
var results <-chan error var results <-chan error
if valid { if valid {
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) chain, _ := NewBlockChain(testdb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals) _, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop() chain.Stop()
} else { } else {
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil) chain, _ := NewBlockChain(testdb, nil, gspec, nil, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{}, nil, nil)
_, results = chain.engine.VerifyHeaders(chain, headers, seals) _, results = chain.engine.VerifyHeaders(chain, headers, seals)
chain.Stop() chain.Stop()
} }
@ -347,7 +348,7 @@ func testHeaderConcurrentAbortion(t *testing.T, threads int) {
defer runtime.GOMAXPROCS(old) defer runtime.GOMAXPROCS(old)
// Start the verifications and immediately abort // Start the verifications and immediately abort
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil) chain, _ := NewBlockChain(testdb, nil, gspec, nil, ethash.NewFakeDelayer(time.Millisecond), vm.Config{}, nil, nil)
defer chain.Stop() defer chain.Stop()
abort, results := chain.engine.VerifyHeaders(chain, headers, seals) abort, results := chain.engine.VerifyHeaders(chain, headers, seals)

View file

@ -23,6 +23,7 @@ import (
"io" "io"
"math/big" "math/big"
"sort" "sort"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -51,6 +52,7 @@ var (
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil) headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
@ -191,6 +193,7 @@ type BlockChain struct {
currentBlock atomic.Value // Current head of the block chain currentBlock atomic.Value // Current head of the block chain
currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!) currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
currentFinalizedBlock atomic.Value // Current finalized head currentFinalizedBlock atomic.Value // Current finalized head
currentSafeBlock atomic.Value // Current safe head
stateCache state.Database // State database to reuse between imports (contains state cache) stateCache state.Database // State database to reuse between imports (contains state cache)
bodyCache *lru.Cache // Cache for the most recent block bodies bodyCache *lru.Cache // Cache for the most recent block bodies
@ -216,7 +219,7 @@ type BlockChain struct {
// NewBlockChain returns a fully initialised block chain using information // NewBlockChain returns a fully initialised block chain using information
// available in the database. It initialises the default Ethereum Validator // available in the database. It initialises the default Ethereum Validator
// and Processor. // and Processor.
func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *params.ChainConfig, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) { func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis, overrides *ChainOverrides, engine consensus.Engine, vmConfig vm.Config, shouldPreserve func(header *types.Header) bool, txLookupLimit *uint64) (*BlockChain, error) {
if cacheConfig == nil { if cacheConfig == nil {
cacheConfig = defaultCacheConfig cacheConfig = defaultCacheConfig
} }
@ -227,6 +230,21 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
txLookupCache, _ := lru.New(txLookupCacheLimit) txLookupCache, _ := lru.New(txLookupCacheLimit)
futureBlocks, _ := lru.New(maxFutureBlocks) futureBlocks, _ := lru.New(maxFutureBlocks)
// Setup the genesis block, commit the provided genesis specification
// to database if the genesis block is not present yet, or load the
// stored one from database.
chainConfig, genesisHash, genesisErr := SetupGenesisBlockWithOverride(db, genesis, overrides)
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
return nil, genesisErr
}
log.Info("")
log.Info(strings.Repeat("-", 153))
for _, line := range strings.Split(chainConfig.String(), "\n") {
log.Info(line)
}
log.Info(strings.Repeat("-", 153))
log.Info("")
bc := &BlockChain{ bc := &BlockChain{
chainConfig: chainConfig, chainConfig: chainConfig,
cacheConfig: cacheConfig, cacheConfig: cacheConfig,
@ -267,6 +285,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
bc.currentBlock.Store(nilBlock) bc.currentBlock.Store(nilBlock)
bc.currentFastBlock.Store(nilBlock) bc.currentFastBlock.Store(nilBlock)
bc.currentFinalizedBlock.Store(nilBlock) bc.currentFinalizedBlock.Store(nilBlock)
bc.currentSafeBlock.Store(nilBlock)
// Initialize the chain with ancient data if it isn't empty. // Initialize the chain with ancient data if it isn't empty.
var txIndexBlock uint64 var txIndexBlock uint64
@ -406,6 +425,12 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
triedb.SaveCachePeriodically(bc.cacheConfig.TrieCleanJournal, bc.cacheConfig.TrieCleanRejournal, bc.quit) triedb.SaveCachePeriodically(bc.cacheConfig.TrieCleanJournal, bc.cacheConfig.TrieCleanRejournal, bc.quit)
}() }()
} }
// Rewind the chain in case of an incompatible config upgrade.
if compat, ok := genesisErr.(*params.ConfigCompatError); ok {
log.Warn("Rewinding chain to upgrade configuration", "err", compat)
bc.SetHead(compat.RewindTo)
rawdb.WriteChainConfig(db, genesisHash, chainConfig)
}
return bc, nil return bc, nil
} }
@ -464,11 +489,15 @@ func (bc *BlockChain) loadLastState() error {
} }
} }
// Restore the last known finalized block // Restore the last known finalized block and safe block
// Note: the safe block is not stored on disk and it is set to the last
// known finalized block on startup
if head := rawdb.ReadFinalizedBlockHash(bc.db); head != (common.Hash{}) { if head := rawdb.ReadFinalizedBlockHash(bc.db); head != (common.Hash{}) {
if block := bc.GetBlockByHash(head); block != nil { if block := bc.GetBlockByHash(head); block != nil {
bc.currentFinalizedBlock.Store(block) bc.currentFinalizedBlock.Store(block)
headFinalizedBlockGauge.Update(int64(block.NumberU64())) headFinalizedBlockGauge.Update(int64(block.NumberU64()))
bc.currentSafeBlock.Store(block)
headSafeBlockGauge.Update(int64(block.NumberU64()))
} }
} }
// Issue a status log for the user // Issue a status log for the user
@ -504,8 +533,23 @@ func (bc *BlockChain) SetHead(head uint64) error {
// SetFinalized sets the finalized block. // SetFinalized sets the finalized block.
func (bc *BlockChain) SetFinalized(block *types.Block) { func (bc *BlockChain) SetFinalized(block *types.Block) {
bc.currentFinalizedBlock.Store(block) bc.currentFinalizedBlock.Store(block)
if block != nil {
rawdb.WriteFinalizedBlockHash(bc.db, block.Hash()) rawdb.WriteFinalizedBlockHash(bc.db, block.Hash())
headFinalizedBlockGauge.Update(int64(block.NumberU64())) headFinalizedBlockGauge.Update(int64(block.NumberU64()))
} else {
rawdb.WriteFinalizedBlockHash(bc.db, common.Hash{})
headFinalizedBlockGauge.Update(0)
}
}
// SetSafe sets the safe block.
func (bc *BlockChain) SetSafe(block *types.Block) {
bc.currentSafeBlock.Store(block)
if block != nil {
headSafeBlockGauge.Update(int64(block.NumberU64()))
} else {
headSafeBlockGauge.Update(0)
}
} }
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition // setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
@ -663,6 +707,16 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bo
bc.txLookupCache.Purge() bc.txLookupCache.Purge()
bc.futureBlocks.Purge() bc.futureBlocks.Purge()
// Clear safe block, finalized block if needed
if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.NumberU64() {
log.Warn("SetHead invalidated safe block")
bc.SetSafe(nil)
}
if finalized := bc.CurrentFinalizedBlock(); finalized != nil && head < finalized.NumberU64() {
log.Error("SetHead invalidated finalized block")
bc.SetFinalized(nil)
}
return rootNumber, bc.loadLastState() return rootNumber, bc.loadLastState()
} }
@ -674,7 +728,7 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
if block == nil { if block == nil {
return fmt.Errorf("non existent block [%x..]", hash[:4]) return fmt.Errorf("non existent block [%x..]", hash[:4])
} }
if _, err := trie.NewSecure(common.Hash{}, block.Root(), bc.stateCache.TrieDB()); err != nil { if _, err := trie.NewStateTrie(common.Hash{}, block.Root(), bc.stateCache.TrieDB()); err != nil {
return err return err
} }
@ -861,6 +915,10 @@ func (bc *BlockChain) Stop() {
log.Error("Dangling trie nodes after full cleanup") log.Error("Dangling trie nodes after full cleanup")
} }
} }
// Flush the collected preimages to disk
if err := bc.stateCache.TrieDB().CommitPreimages(); err != nil {
log.Error("Failed to commit trie preimages", "err", err)
}
// Ensure all live cached entries be saved into disk, so that we can skip // Ensure all live cached entries be saved into disk, so that we can skip
// cache warmup when node restarts. // cache warmup when node restarts.
if bc.cacheConfig.TrieCleanJournal != "" { if bc.cacheConfig.TrieCleanJournal != "" {
@ -1212,7 +1270,7 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error {
// writeBlockWithState writes block, metadata and corresponding state data to the // writeBlockWithState writes block, metadata and corresponding state data to the
// database. // database.
func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB) error { func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error {
// Calculate the total difficulty of the block // Calculate the total difficulty of the block
ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1)
if ptd == nil { if ptd == nil {
@ -1307,7 +1365,7 @@ func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead. // writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
// This function expects the chain mutex to be held. // This function expects the chain mutex to be held.
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) {
if err := bc.writeBlockWithState(block, receipts, logs, state); err != nil { if err := bc.writeBlockWithState(block, receipts, state); err != nil {
return NonStatTy, err return NonStatTy, err
} }
currentBlock := bc.CurrentBlock() currentBlock := bc.CurrentBlock()
@ -1339,7 +1397,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
} }
// In theory we should fire a ChainHeadEvent when we inject // In theory we should fire a ChainHeadEvent when we inject
// a canonical block, but sometimes we can insert a batch of // a canonical block, but sometimes we can insert a batch of
// canonicial blocks. Avoid firing too many ChainHeadEvents, // canonical blocks. Avoid firing too many ChainHeadEvents,
// we will fire an accumulated ChainHeadEvent and disable fire // we will fire an accumulated ChainHeadEvent and disable fire
// event here. // event here.
if emitHeadEvent { if emitHeadEvent {
@ -1576,7 +1634,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
// block in the middle. It can only happen in the clique chain. Whenever // block in the middle. It can only happen in the clique chain. Whenever
// we insert blocks via `insertSideChain`, we only commit `td`, `header` // we insert blocks via `insertSideChain`, we only commit `td`, `header`
// and `body` if it's non-existent. Since we don't have receipts without // and `body` if it's non-existent. Since we don't have receipts without
// reexecution, so nothing to commit. But if the sidechain will be adpoted // reexecution, so nothing to commit. But if the sidechain will be adopted
// as the canonical chain eventually, it needs to be reexecuted for missing // as the canonical chain eventually, it needs to be reexecuted for missing
// state, but if it's this special case here(skip reexecution) we will lose // state, but if it's this special case here(skip reexecution) we will lose
// the empty receipt entry. // the empty receipt entry.
@ -1671,7 +1729,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
var status WriteStatus var status WriteStatus
if !setHead { if !setHead {
// Don't set the head, only insert the block // Don't set the head, only insert the block
err = bc.writeBlockWithState(block, receipts, logs, statedb) err = bc.writeBlockWithState(block, receipts, statedb)
} else { } else {
status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false) status, err = bc.writeBlockAndSetHead(block, receipts, logs, statedb, false)
} }

View file

@ -55,6 +55,12 @@ func (bc *BlockChain) CurrentFinalizedBlock() *types.Block {
return bc.currentFinalizedBlock.Load().(*types.Block) return bc.currentFinalizedBlock.Load().(*types.Block)
} }
// CurrentSafeBlock retrieves the current safe block of the canonical
// chain. The block is retrieved from the blockchain's internal cache.
func (bc *BlockChain) CurrentSafeBlock() *types.Block {
return bc.currentSafeBlock.Load().(*types.Block)
}
// HasHeader checks if a block header is present in the database or not, caching // HasHeader checks if a block header is present in the database or not, caching
// it if present. // it if present.
func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool { func (bc *BlockChain) HasHeader(hash common.Hash, number uint64) bool {
@ -131,6 +137,9 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
if bc.blockCache.Contains(hash) { if bc.blockCache.Contains(hash) {
return true return true
} }
if !bc.HasHeader(hash, number) {
return false
}
return rawdb.HasBody(bc.db, hash, number) return rawdb.HasBody(bc.db, hash, number)
} }

View file

@ -564,7 +564,7 @@ func testShortReorgedSnapSyncingRepair(t *testing.T, snapshots bool) {
// Tests a recovery for a long canonical chain with frozen blocks where a recent // Tests a recovery for a long canonical chain with frozen blocks where a recent
// block - newer than the ancient limit - was already committed to disk and then // block - newer than the ancient limit - was already committed to disk and then
// the process crashed. In this case we expect the chain to be rolled back to the // the process crashed. In this case we expect the chain to be rolled back to the
// committed block, with everything afterwads kept as fast sync data. // committed block, with everything afterwards kept as fast sync data.
func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) } func TestLongShallowRepair(t *testing.T) { testLongShallowRepair(t, false) }
func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) } func TestLongShallowRepairWithSnapshots(t *testing.T) { testLongShallowRepair(t, true) }
@ -609,7 +609,7 @@ func testLongShallowRepair(t *testing.T, snapshots bool) {
// Tests a recovery for a long canonical chain with frozen blocks where a recent // Tests a recovery for a long canonical chain with frozen blocks where a recent
// block - older than the ancient limit - was already committed to disk and then // block - older than the ancient limit - was already committed to disk and then
// the process crashed. In this case we expect the chain to be rolled back to the // the process crashed. In this case we expect the chain to be rolled back to the
// committed block, with everything afterwads deleted. // committed block, with everything afterwards deleted.
func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) } func TestLongDeepRepair(t *testing.T) { testLongDeepRepair(t, false) }
func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) } func TestLongDeepRepairWithSnapshots(t *testing.T) { testLongDeepRepair(t, true) }
@ -653,7 +653,7 @@ func testLongDeepRepair(t *testing.T, snapshots bool) {
// Tests a recovery for a long canonical chain with frozen blocks where the fast // Tests a recovery for a long canonical chain with frozen blocks where the fast
// sync pivot point - newer than the ancient limit - was already committed, after // sync pivot point - newer than the ancient limit - was already committed, after
// which the process crashed. In this case we expect the chain to be rolled back // which the process crashed. In this case we expect the chain to be rolled back
// to the committed block, with everything afterwads kept as fast sync data. // to the committed block, with everything afterwards kept as fast sync data.
func TestLongSnapSyncedShallowRepair(t *testing.T) { func TestLongSnapSyncedShallowRepair(t *testing.T) {
testLongSnapSyncedShallowRepair(t, false) testLongSnapSyncedShallowRepair(t, false)
} }
@ -702,7 +702,7 @@ func testLongSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
// Tests a recovery for a long canonical chain with frozen blocks where the fast // Tests a recovery for a long canonical chain with frozen blocks where the fast
// sync pivot point - older than the ancient limit - was already committed, after // sync pivot point - older than the ancient limit - was already committed, after
// which the process crashed. In this case we expect the chain to be rolled back // which the process crashed. In this case we expect the chain to be rolled back
// to the committed block, with everything afterwads deleted. // to the committed block, with everything afterwards deleted.
func TestLongSnapSyncedDeepRepair(t *testing.T) { testLongSnapSyncedDeepRepair(t, false) } func TestLongSnapSyncedDeepRepair(t *testing.T) { testLongSnapSyncedDeepRepair(t, false) }
func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) } func TestLongSnapSyncedDeepRepairWithSnapshots(t *testing.T) { testLongSnapSyncedDeepRepair(t, true) }
@ -843,7 +843,7 @@ func testLongSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
// side chain, where a recent block - newer than the ancient limit - was already // side chain, where a recent block - newer than the ancient limit - was already
// committed to disk and then the process crashed. In this test scenario the side // committed to disk and then the process crashed. In this test scenario the side
// chain is below the committed block. In this case we expect the chain to be // chain is below the committed block. In this case we expect the chain to be
// rolled back to the committed block, with everything afterwads kept as fast // rolled back to the committed block, with everything afterwards kept as fast
// sync data; the side chain completely nuked by the freezer. // sync data; the side chain completely nuked by the freezer.
func TestLongOldForkedShallowRepair(t *testing.T) { func TestLongOldForkedShallowRepair(t *testing.T) {
testLongOldForkedShallowRepair(t, false) testLongOldForkedShallowRepair(t, false)
@ -895,7 +895,7 @@ func testLongOldForkedShallowRepair(t *testing.T, snapshots bool) {
// side chain, where a recent block - older than the ancient limit - was already // side chain, where a recent block - older than the ancient limit - was already
// committed to disk and then the process crashed. In this test scenario the side // committed to disk and then the process crashed. In this test scenario the side
// chain is below the committed block. In this case we expect the canonical chain // chain is below the committed block. In this case we expect the canonical chain
// to be rolled back to the committed block, with everything afterwads deleted; // to be rolled back to the committed block, with everything afterwards deleted;
// the side chain completely nuked by the freezer. // the side chain completely nuked by the freezer.
func TestLongOldForkedDeepRepair(t *testing.T) { testLongOldForkedDeepRepair(t, false) } func TestLongOldForkedDeepRepair(t *testing.T) { testLongOldForkedDeepRepair(t, false) }
func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) } func TestLongOldForkedDeepRepairWithSnapshots(t *testing.T) { testLongOldForkedDeepRepair(t, true) }
@ -942,7 +942,7 @@ func testLongOldForkedDeepRepair(t *testing.T, snapshots bool) {
// side chain, where the fast sync pivot point - newer than the ancient limit - // side chain, where the fast sync pivot point - newer than the ancient limit -
// was already committed to disk and then the process crashed. In this test scenario // was already committed to disk and then the process crashed. In this test scenario
// the side chain is below the committed block. In this case we expect the chain // the side chain is below the committed block. In this case we expect the chain
// to be rolled back to the committed block, with everything afterwads kept as // to be rolled back to the committed block, with everything afterwards kept as
// fast sync data; the side chain completely nuked by the freezer. // fast sync data; the side chain completely nuked by the freezer.
func TestLongOldForkedSnapSyncedShallowRepair(t *testing.T) { func TestLongOldForkedSnapSyncedShallowRepair(t *testing.T) {
testLongOldForkedSnapSyncedShallowRepair(t, false) testLongOldForkedSnapSyncedShallowRepair(t, false)
@ -994,7 +994,7 @@ func testLongOldForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
// side chain, where the fast sync pivot point - older than the ancient limit - // side chain, where the fast sync pivot point - older than the ancient limit -
// was already committed to disk and then the process crashed. In this test scenario // was already committed to disk and then the process crashed. In this test scenario
// the side chain is below the committed block. In this case we expect the canonical // the side chain is below the committed block. In this case we expect the canonical
// chain to be rolled back to the committed block, with everything afterwads deleted; // chain to be rolled back to the committed block, with everything afterwards deleted;
// the side chain completely nuked by the freezer. // the side chain completely nuked by the freezer.
func TestLongOldForkedSnapSyncedDeepRepair(t *testing.T) { func TestLongOldForkedSnapSyncedDeepRepair(t *testing.T) {
testLongOldForkedSnapSyncedDeepRepair(t, false) testLongOldForkedSnapSyncedDeepRepair(t, false)
@ -1149,7 +1149,7 @@ func testLongOldForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
// side chain, where a recent block - newer than the ancient limit - was already // side chain, where a recent block - newer than the ancient limit - was already
// committed to disk and then the process crashed. In this test scenario the side // committed to disk and then the process crashed. In this test scenario the side
// chain is above the committed block. In this case we expect the chain to be // chain is above the committed block. In this case we expect the chain to be
// rolled back to the committed block, with everything afterwads kept as fast // rolled back to the committed block, with everything afterwards kept as fast
// sync data; the side chain completely nuked by the freezer. // sync data; the side chain completely nuked by the freezer.
func TestLongNewerForkedShallowRepair(t *testing.T) { func TestLongNewerForkedShallowRepair(t *testing.T) {
testLongNewerForkedShallowRepair(t, false) testLongNewerForkedShallowRepair(t, false)
@ -1201,7 +1201,7 @@ func testLongNewerForkedShallowRepair(t *testing.T, snapshots bool) {
// side chain, where a recent block - older than the ancient limit - was already // side chain, where a recent block - older than the ancient limit - was already
// committed to disk and then the process crashed. In this test scenario the side // committed to disk and then the process crashed. In this test scenario the side
// chain is above the committed block. In this case we expect the canonical chain // chain is above the committed block. In this case we expect the canonical chain
// to be rolled back to the committed block, with everything afterwads deleted; // to be rolled back to the committed block, with everything afterwards deleted;
// the side chain completely nuked by the freezer. // the side chain completely nuked by the freezer.
func TestLongNewerForkedDeepRepair(t *testing.T) { testLongNewerForkedDeepRepair(t, false) } func TestLongNewerForkedDeepRepair(t *testing.T) { testLongNewerForkedDeepRepair(t, false) }
func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) } func TestLongNewerForkedDeepRepairWithSnapshots(t *testing.T) { testLongNewerForkedDeepRepair(t, true) }
@ -1248,7 +1248,7 @@ func testLongNewerForkedDeepRepair(t *testing.T, snapshots bool) {
// side chain, where the fast sync pivot point - newer than the ancient limit - // side chain, where the fast sync pivot point - newer than the ancient limit -
// was already committed to disk and then the process crashed. In this test scenario // was already committed to disk and then the process crashed. In this test scenario
// the side chain is above the committed block. In this case we expect the chain // the side chain is above the committed block. In this case we expect the chain
// to be rolled back to the committed block, with everything afterwads kept as fast // to be rolled back to the committed block, with everything afterwards kept as fast
// sync data; the side chain completely nuked by the freezer. // sync data; the side chain completely nuked by the freezer.
func TestLongNewerForkedSnapSyncedShallowRepair(t *testing.T) { func TestLongNewerForkedSnapSyncedShallowRepair(t *testing.T) {
testLongNewerForkedSnapSyncedShallowRepair(t, false) testLongNewerForkedSnapSyncedShallowRepair(t, false)
@ -1300,7 +1300,7 @@ func testLongNewerForkedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
// side chain, where the fast sync pivot point - older than the ancient limit - // side chain, where the fast sync pivot point - older than the ancient limit -
// was already committed to disk and then the process crashed. In this test scenario // was already committed to disk and then the process crashed. In this test scenario
// the side chain is above the committed block. In this case we expect the canonical // the side chain is above the committed block. In this case we expect the canonical
// chain to be rolled back to the committed block, with everything afterwads deleted; // chain to be rolled back to the committed block, with everything afterwards deleted;
// the side chain completely nuked by the freezer. // the side chain completely nuked by the freezer.
func TestLongNewerForkedSnapSyncedDeepRepair(t *testing.T) { func TestLongNewerForkedSnapSyncedDeepRepair(t *testing.T) {
testLongNewerForkedSnapSyncedDeepRepair(t, false) testLongNewerForkedSnapSyncedDeepRepair(t, false)
@ -1454,7 +1454,7 @@ func testLongNewerForkedSnapSyncingDeepRepair(t *testing.T, snapshots bool) {
// Tests a recovery for a long canonical chain with frozen blocks and a longer side // Tests a recovery for a long canonical chain with frozen blocks and a longer side
// chain, where a recent block - newer than the ancient limit - was already committed // chain, where a recent block - newer than the ancient limit - was already committed
// to disk and then the process crashed. In this case we expect the chain to be // to disk and then the process crashed. In this case we expect the chain to be
// rolled back to the committed block, with everything afterwads kept as fast sync // rolled back to the committed block, with everything afterwards kept as fast sync
// data. The side chain completely nuked by the freezer. // data. The side chain completely nuked by the freezer.
func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) } func TestLongReorgedShallowRepair(t *testing.T) { testLongReorgedShallowRepair(t, false) }
func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) } func TestLongReorgedShallowRepairWithSnapshots(t *testing.T) { testLongReorgedShallowRepair(t, true) }
@ -1501,7 +1501,7 @@ func testLongReorgedShallowRepair(t *testing.T, snapshots bool) {
// Tests a recovery for a long canonical chain with frozen blocks and a longer side // Tests a recovery for a long canonical chain with frozen blocks and a longer side
// chain, where a recent block - older than the ancient limit - was already committed // chain, where a recent block - older than the ancient limit - was already committed
// to disk and then the process crashed. In this case we expect the canonical chains // to disk and then the process crashed. In this case we expect the canonical chains
// to be rolled back to the committed block, with everything afterwads deleted. The // to be rolled back to the committed block, with everything afterwards deleted. The
// side chain completely nuked by the freezer. // side chain completely nuked by the freezer.
func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) } func TestLongReorgedDeepRepair(t *testing.T) { testLongReorgedDeepRepair(t, false) }
func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) } func TestLongReorgedDeepRepairWithSnapshots(t *testing.T) { testLongReorgedDeepRepair(t, true) }
@ -1548,7 +1548,7 @@ func testLongReorgedDeepRepair(t *testing.T, snapshots bool) {
// side chain, where the fast sync pivot point - newer than the ancient limit - // side chain, where the fast sync pivot point - newer than the ancient limit -
// was already committed to disk and then the process crashed. In this case we // was already committed to disk and then the process crashed. In this case we
// expect the chain to be rolled back to the committed block, with everything // expect the chain to be rolled back to the committed block, with everything
// afterwads kept as fast sync data. The side chain completely nuked by the // afterwards kept as fast sync data. The side chain completely nuked by the
// freezer. // freezer.
func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) { func TestLongReorgedSnapSyncedShallowRepair(t *testing.T) {
testLongReorgedSnapSyncedShallowRepair(t, false) testLongReorgedSnapSyncedShallowRepair(t, false)
@ -1600,7 +1600,7 @@ func testLongReorgedSnapSyncedShallowRepair(t *testing.T, snapshots bool) {
// side chain, where the fast sync pivot point - older than the ancient limit - // side chain, where the fast sync pivot point - older than the ancient limit -
// was already committed to disk and then the process crashed. In this case we // was already committed to disk and then the process crashed. In this case we
// expect the canonical chains to be rolled back to the committed block, with // expect the canonical chains to be rolled back to the committed block, with
// everything afterwads deleted. The side chain completely nuked by the freezer. // everything afterwards deleted. The side chain completely nuked by the freezer.
func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) { func TestLongReorgedSnapSyncedDeepRepair(t *testing.T) {
testLongReorgedSnapSyncedDeepRepair(t, false) testLongReorgedSnapSyncedDeepRepair(t, false)
} }
@ -1764,7 +1764,11 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
// Initialize a fresh chain // Initialize a fresh chain
var ( var (
genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.AllEthashProtocolChanges,
}
genesis = gspec.MustCommit(db)
engine = ethash.NewFullFaker() engine = ethash.NewFullFaker()
config = &CacheConfig{ config = &CacheConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
@ -1778,7 +1782,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256 config.SnapshotLimit = 256
config.SnapshotWait = true config.SnapshotWait = true
} }
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -1831,7 +1835,7 @@ func testRepair(t *testing.T, tt *rewindTest, snapshots bool) {
} }
defer db.Close() defer db.Close()
newChain, err := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) newChain, err := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -1888,7 +1892,11 @@ func TestIssue23496(t *testing.T) {
// Initialize a fresh chain // Initialize a fresh chain
var ( var (
genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec = &Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}
genesis = gspec.MustCommit(db)
engine = ethash.NewFullFaker() engine = ethash.NewFullFaker()
config = &CacheConfig{ config = &CacheConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
@ -1898,7 +1906,7 @@ func TestIssue23496(t *testing.T) {
SnapshotWait: true, SnapshotWait: true,
} }
) )
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -1942,7 +1950,7 @@ func TestIssue23496(t *testing.T) {
} }
defer db.Close() defer db.Close()
chain, err = NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) chain, err = NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }

View file

@ -1964,7 +1964,11 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
// Initialize a fresh chain // Initialize a fresh chain
var ( var (
genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.AllEthashProtocolChanges,
}
genesis = gspec.MustCommit(db)
engine = ethash.NewFullFaker() engine = ethash.NewFullFaker()
config = &CacheConfig{ config = &CacheConfig{
TrieCleanLimit: 256, TrieCleanLimit: 256,
@ -1977,7 +1981,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
config.SnapshotLimit = 256 config.SnapshotLimit = 256
config.SnapshotWait = true config.SnapshotWait = true
} }
chain, err := NewBlockChain(db, config, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(db, config, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }

View file

@ -54,6 +54,7 @@ type snapshotTestBasic struct {
db ethdb.Database db ethdb.Database
gendb ethdb.Database gendb ethdb.Database
engine consensus.Engine engine consensus.Engine
gspec *Genesis
} }
func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) { func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Block) {
@ -66,7 +67,11 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
} }
// Initialize a fresh chain // Initialize a fresh chain
var ( var (
genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.AllEthashProtocolChanges,
}
genesis = gspec.MustCommit(db)
engine = ethash.NewFullFaker() engine = ethash.NewFullFaker()
gendb = rawdb.NewMemoryDatabase() gendb = rawdb.NewMemoryDatabase()
@ -75,7 +80,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
// will happen during the block insertion. // will happen during the block insertion.
cacheConfig = defaultCacheConfig cacheConfig = defaultCacheConfig
) )
chain, err := NewBlockChain(db, cacheConfig, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(db, cacheConfig, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to create chain: %v", err) t.Fatalf("Failed to create chain: %v", err)
} }
@ -118,6 +123,7 @@ func (basic *snapshotTestBasic) prepare(t *testing.T) (*BlockChain, []*types.Blo
basic.db = db basic.db = db
basic.gendb = gendb basic.gendb = gendb
basic.engine = engine basic.engine = engine
basic.gspec = gspec
return chain, blocks return chain, blocks
} }
@ -219,7 +225,7 @@ func (snaptest *snapshotTest) test(t *testing.T) {
// Restart the chain normally // Restart the chain normally
chain.Stop() chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err := NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -255,13 +261,13 @@ func (snaptest *crashSnapshotTest) test(t *testing.T) {
// the crash, we do restart twice here: one after the crash and one // the crash, we do restart twice here: one after the crash and one
// after the normal stop. It's used to ensure the broken snapshot // after the normal stop. It's used to ensure the broken snapshot
// can be detected all the time. // can be detected all the time.
newchain, err := NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err := NewBlockChain(newdb, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
newchain.Stop() newchain.Stop()
newchain, err = NewBlockChain(newdb, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err = NewBlockChain(newdb, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -297,7 +303,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, SnapshotLimit: 0,
} }
newchain, err := NewBlockChain(snaptest.db, cacheConfig, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err := NewBlockChain(snaptest.db, cacheConfig, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -305,7 +311,7 @@ func (snaptest *gappedSnapshotTest) test(t *testing.T) {
newchain.Stop() newchain.Stop()
// Restart the chain with enabling the snapshot // Restart the chain with enabling the snapshot
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err = NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -333,7 +339,7 @@ func (snaptest *setHeadSnapshotTest) test(t *testing.T) {
chain.SetHead(snaptest.setHead) chain.SetHead(snaptest.setHead)
chain.Stop() chain.Stop()
newchain, err := NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err := NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -368,7 +374,7 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
TrieTimeLimit: 5 * time.Minute, TrieTimeLimit: 5 * time.Minute,
SnapshotLimit: 0, SnapshotLimit: 0,
} }
newchain, err := NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err := NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
@ -384,13 +390,13 @@ func (snaptest *wipeCrashSnapshotTest) test(t *testing.T) {
SnapshotLimit: 256, SnapshotLimit: 256,
SnapshotWait: false, // Don't wait rebuild SnapshotWait: false, // Don't wait rebuild
} }
_, err = NewBlockChain(snaptest.db, config, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) _, err = NewBlockChain(snaptest.db, config, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }
// Simulate the blockchain crash. // Simulate the blockchain crash.
newchain, err = NewBlockChain(snaptest.db, nil, params.AllEthashProtocolChanges, snaptest.engine, vm.Config{}, nil, nil) newchain, err = NewBlockChain(snaptest.db, nil, snaptest.gspec, nil, snaptest.engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("Failed to recreate chain: %v", err) t.Fatalf("Failed to recreate chain: %v", err)
} }

View file

@ -54,11 +54,15 @@ var (
func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) { func newCanonical(engine consensus.Engine, n int, full bool) (ethdb.Database, *BlockChain, error) {
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.AllEthashProtocolChanges,
}
genesis = gspec.MustCommit(db)
) )
// Initialize a fresh chain with only a genesis block // Initialize a fresh chain with only a genesis block
blockchain, _ := NewBlockChain(db, nil, params.AllEthashProtocolChanges, engine, vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
// Create and inject the requested chain // Create and inject the requested chain
if n == 0 { if n == 0 {
return db, blockchain, nil return db, blockchain, nil
@ -654,7 +658,11 @@ func testReorgBadHashes(t *testing.T, full bool) {
blockchain.Stop() blockchain.Stop()
// Create a new BlockChain and check that it rolled back the state. // Create a new BlockChain and check that it rolled back the state.
ncm, err := NewBlockChain(blockchain.db, nil, blockchain.chainConfig, ethash.NewFaker(), vm.Config{}, nil, nil) gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.AllEthashProtocolChanges,
}
ncm, err := NewBlockChain(blockchain.db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create new chain manager: %v", err) t.Fatalf("failed to create new chain manager: %v", err)
} }
@ -759,15 +767,15 @@ func TestFastVsFullChains(t *testing.T) {
block.AddTx(tx) block.AddTx(tx)
} }
} }
// If the block number is a multiple of 5, add a few bonus uncles to the block // If the block number is a multiple of 5, add an uncle to the block
if i%5 == 5 { if i%5 == 4 {
block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))}) block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 2).Hash(), Number: big.NewInt(int64(i))})
} }
}) })
// Import the chain as an archive node for the comparison baseline // Import the chain as an archive node for the comparison baseline
archiveDb := rawdb.NewMemoryDatabase() archiveDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(archiveDb) gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) archive, _ := NewBlockChain(archiveDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer archive.Stop() defer archive.Stop()
if n, err := archive.InsertChain(blocks); err != nil { if n, err := archive.InsertChain(blocks); err != nil {
@ -776,7 +784,7 @@ func TestFastVsFullChains(t *testing.T) {
// Fast import the chain as a non-archive node to test // Fast import the chain as a non-archive node to test
fastDb := rawdb.NewMemoryDatabase() fastDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(fastDb) gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) fast, _ := NewBlockChain(fastDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer fast.Stop() defer fast.Stop()
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
@ -797,7 +805,7 @@ func TestFastVsFullChains(t *testing.T) {
} }
defer ancientDb.Close() defer ancientDb.Close()
gspec.MustCommit(ancientDb) gspec.MustCommit(ancientDb)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop() defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
@ -915,7 +923,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
archiveCaching := *defaultCacheConfig archiveCaching := *defaultCacheConfig
archiveCaching.TrieDirtyDisabled = true archiveCaching.TrieDirtyDisabled = true
archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) archive, _ := NewBlockChain(archiveDb, &archiveCaching, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := archive.InsertChain(blocks); err != nil { if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err) t.Fatalf("failed to process block %d: %v", n, err)
} }
@ -928,7 +936,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated // Import the chain as a non-archive node and ensure all pointers are updated
fastDb := makeDb() fastDb := makeDb()
defer fastDb.Close() defer fastDb.Close()
fast, _ := NewBlockChain(fastDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) fast, _ := NewBlockChain(fastDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer fast.Stop() defer fast.Stop()
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
@ -948,7 +956,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a ancient-first node and ensure all pointers are updated // Import the chain as a ancient-first node and ensure all pointers are updated
ancientDb := makeDb() ancientDb := makeDb()
defer ancientDb.Close() defer ancientDb.Close()
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop() defer ancient.Stop()
if n, err := ancient.InsertHeaderChain(headers, 1); err != nil { if n, err := ancient.InsertHeaderChain(headers, 1); err != nil {
@ -967,7 +975,7 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a light node and ensure all pointers are updated // Import the chain as a light node and ensure all pointers are updated
lightDb := makeDb() lightDb := makeDb()
defer lightDb.Close() defer lightDb.Close()
light, _ := NewBlockChain(lightDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) light, _ := NewBlockChain(lightDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if n, err := light.InsertHeaderChain(headers, 1); err != nil { if n, err := light.InsertHeaderChain(headers, 1); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err) t.Fatalf("failed to insert header %d: %v", n, err)
} }
@ -1036,7 +1044,7 @@ func TestChainTxReorgs(t *testing.T) {
} }
}) })
// Import the chain. This runs all block validation rules. // Import the chain. This runs all block validation rules.
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
if i, err := blockchain.InsertChain(chain); err != nil { if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err) t.Fatalf("failed to insert original chain[%d]: %v", i, err)
} }
@ -1106,7 +1114,7 @@ func TestLogReorgs(t *testing.T) {
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
) )
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop() defer blockchain.Stop()
rmLogsCh := make(chan RemovedLogsEvent) rmLogsCh := make(chan RemovedLogsEvent)
@ -1159,7 +1167,7 @@ func TestLogRebirth(t *testing.T) {
genesis = gspec.MustCommit(db) genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
engine = ethash.NewFaker() engine = ethash.NewFaker()
blockchain, _ = NewBlockChain(db, nil, gspec.Config, engine, vm.Config{}, nil, nil) blockchain, _ = NewBlockChain(db, nil, gspec, nil, engine, vm.Config{}, nil, nil)
) )
defer blockchain.Stop() defer blockchain.Stop()
@ -1222,7 +1230,7 @@ func TestSideLogRebirth(t *testing.T) {
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}} gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000000)}}}
genesis = gspec.MustCommit(db) genesis = gspec.MustCommit(db)
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
blockchain, _ = NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ = NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
) )
defer blockchain.Stop() defer blockchain.Stop()
@ -1235,7 +1243,6 @@ func TestSideLogRebirth(t *testing.T) {
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) {
if i == 1 { if i == 1 {
gen.OffsetTime(-9) // higher block difficulty gen.OffsetTime(-9) // higher block difficulty
} }
}) })
if _, err := blockchain.InsertChain(chain); err != nil { if _, err := blockchain.InsertChain(chain); err != nil {
@ -1297,7 +1304,7 @@ func TestReorgSideEvent(t *testing.T) {
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
) )
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop() defer blockchain.Stop()
chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {}) chain, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, gen *BlockGen) {})
@ -1364,7 +1371,6 @@ done:
t.Errorf("unexpected event fired: %v", e) t.Errorf("unexpected event fired: %v", e)
case <-time.After(250 * time.Millisecond): case <-time.After(250 * time.Millisecond):
} }
} }
// Tests if the canonical block can be fetched from the database during chain insertion. // Tests if the canonical block can be fetched from the database during chain insertion.
@ -1429,7 +1435,7 @@ func TestEIP155Transition(t *testing.T) {
genesis = gspec.MustCommit(db) genesis = gspec.MustCommit(db)
) )
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop() defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) { blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 4, func(i int, block *BlockGen) {
@ -1537,7 +1543,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
} }
genesis = gspec.MustCommit(db) genesis = gspec.MustCommit(db)
) )
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop() defer blockchain.Stop()
blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) { blocks, _ := GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 3, func(i int, block *BlockGen) {
@ -1594,7 +1600,11 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}
genesis := gspec.MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
// Generate a bunch of fork blocks, each side forking from the canonical chain // Generate a bunch of fork blocks, each side forking from the canonical chain
@ -1612,7 +1622,7 @@ func TestBlockchainHeaderchainReorgConsistency(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb) (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1639,7 +1649,11 @@ func TestTrieForkGC(t *testing.T) {
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
genesis := gspec.MustCommit(db)
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
// Generate a bunch of fork blocks, each side forking from the canonical chain // Generate a bunch of fork blocks, each side forking from the canonical chain
@ -1654,9 +1668,9 @@ func TestTrieForkGC(t *testing.T) {
} }
// Import the canonical and fork chain side by side, forcing the trie cache to cache both // Import the canonical and fork chain side by side, forcing the trie cache to cache both
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1685,7 +1699,11 @@ func TestLargeReorgTrieGC(t *testing.T) {
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
genesis := gspec.MustCommit(db)
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) }) original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
@ -1693,9 +1711,9 @@ func TestLargeReorgTrieGC(t *testing.T) {
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1753,7 +1771,7 @@ func TestBlockchainRecovery(t *testing.T) {
} }
defer ancientDb.Close() defer ancientDb.Close()
gspec.MustCommit(ancientDb) gspec.MustCommit(ancientDb)
ancient, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) ancient, _ := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
headers := make([]*types.Header, len(blocks)) headers := make([]*types.Header, len(blocks))
for i, block := range blocks { for i, block := range blocks {
@ -1773,7 +1791,7 @@ func TestBlockchainRecovery(t *testing.T) {
rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash()) rawdb.WriteHeadFastBlockHash(ancientDb, midBlock.Hash())
// Reopen broken blockchain again // Reopen broken blockchain again
ancient, _ = NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) ancient, _ = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancient.Stop() defer ancient.Stop()
if num := ancient.CurrentBlock().NumberU64(); num != 0 { if num := ancient.CurrentBlock().NumberU64(); num != 0 {
t.Errorf("head block mismatch: have #%v, want #%v", num, 0) t.Errorf("head block mismatch: have #%v, want #%v", num, 0)
@ -1814,15 +1832,15 @@ func TestInsertReceiptChainRollback(t *testing.T) {
} }
// Set up a BlockChain that uses the ancient store. // Set up a BlockChain that uses the ancient store.
frdir := t.TempDir() ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false)
ancientDb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false)
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
defer ancientDb.Close() defer ancientDb.Close()
gspec := Genesis{Config: params.AllEthashProtocolChanges} gspec := Genesis{Config: params.AllEthashProtocolChanges}
gspec.MustCommit(ancientDb) gspec.MustCommit(ancientDb)
ancientChain, _ := NewBlockChain(ancientDb, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) ancientChain, _ := NewBlockChain(ancientDb, nil, &gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer ancientChain.Stop() defer ancientChain.Stop()
// Import the canonical header chain. // Import the canonical header chain.
@ -1870,7 +1888,11 @@ func TestLowDiffLongChain(t *testing.T) {
// Generate a canonical chain to act as the main dataset // Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
genesis := gspec.MustCommit(db)
// We must use a pretty long chain to ensure that the fork doesn't overtake us // We must use a pretty long chain to ensure that the fork doesn't overtake us
// until after at least 128 blocks post tip // until after at least 128 blocks post tip
@ -1881,9 +1903,9 @@ func TestLowDiffLongChain(t *testing.T) {
// Import the canonical chain // Import the canonical chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -1944,12 +1966,12 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
BaseFee: big.NewInt(params.InitialBaseFee), BaseFee: big.NewInt(params.InitialBaseFee),
} }
signer = types.LatestSigner(gspec.Config) signer = types.LatestSigner(gspec.Config)
genesis, _ = gspec.Commit(db) genesis = gspec.MustCommit(db)
) )
// Generate and import the canonical chain // Generate and import the canonical chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, &chainConfig, runEngine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, runEngine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2065,7 +2087,11 @@ func testInsertKnownChainData(t *testing.T, typ string) {
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
Config: params.TestChainConfig,
BaseFee: big.NewInt(params.InitialBaseFee),
}
genesis := gspec.MustCommit(db)
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, engine, db, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) }) blocks, receipts := GenerateChain(params.TestChainConfig, genesis, engine, db, 32, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
// A longer chain but total difficulty is lower. // A longer chain but total difficulty is lower.
@ -2076,15 +2102,14 @@ func testInsertKnownChainData(t *testing.T, typ string) {
b.OffsetTime(-9) // A higher difficulty b.OffsetTime(-9) // A higher difficulty
}) })
// Import the shared chain and the original canonical one // Import the shared chain and the original canonical one
dir := t.TempDir() chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), t.TempDir(), "", false)
chaindb, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), dir, "", false)
if err != nil { if err != nil {
t.Fatalf("failed to create temp freezer db: %v", err) t.Fatalf("failed to create temp freezer db: %v", err)
} }
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(chaindb) gspec.MustCommit(chaindb)
defer chaindb.Close() defer chaindb.Close()
chain, err := NewBlockChain(chaindb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(chaindb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2205,7 +2230,11 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
chainConfig := *params.TestChainConfig chainConfig := *params.TestChainConfig
var ( var (
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
genesis = (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee), Config: &chainConfig}).MustCommit(db) gspec = &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: &chainConfig,
}
genesis = gspec.MustCommit(db)
runMerger = consensus.NewMerger(db) runMerger = consensus.NewMerger(db)
runEngine = beacon.New(ethash.NewFaker()) runEngine = beacon.New(ethash.NewFaker())
genEngine = beacon.New(ethash.NewFaker()) genEngine = beacon.New(ethash.NewFaker())
@ -2244,7 +2273,7 @@ func testInsertKnownChainDataWithMerging(t *testing.T, typ string, mergeHeight i
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(chaindb) (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(chaindb)
defer chaindb.Close() defer chaindb.Close()
chain, err := NewBlockChain(chaindb, nil, &chainConfig, runEngine, vm.Config{}, nil, nil) chain, err := NewBlockChain(chaindb, nil, gspec, nil, runEngine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2352,7 +2381,11 @@ func getLongAndShortChains() (bc *BlockChain, longChain []*types.Block, heavyCha
// Generate a canonical chain to act as the main dataset // Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
genesis := gspec.MustCommit(db)
// Generate and import the canonical chain, // Generate and import the canonical chain,
// Offset the time, to keep the difficulty low // Offset the time, to keep the difficulty low
@ -2360,9 +2393,9 @@ func getLongAndShortChains() (bc *BlockChain, longChain []*types.Block, heavyCha
b.SetCoinbase(common.Address{1}) b.SetCoinbase(common.Address{1})
}) })
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err) return nil, nil, nil, fmt.Errorf("failed to create tester chain: %v", err)
} }
@ -2392,12 +2425,12 @@ func getLongAndShortChains() (bc *BlockChain, longChain []*types.Block, heavyCha
shorterTd.Add(shorterTd, b.Difficulty()) shorterTd.Add(shorterTd, b.Difficulty())
} }
if shorterTd.Cmp(longerTd) <= 0 { if shorterTd.Cmp(longerTd) <= 0 {
return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd) return nil, nil, nil, fmt.Errorf("test is moot, heavyChain td (%v) must be larger than canon td (%v)", shorterTd, longerTd)
} }
longerNum := longChain[len(longChain)-1].NumberU64() longerNum := longChain[len(longChain)-1].NumberU64()
shorterNum := heavyChain[len(heavyChain)-1].NumberU64() shorterNum := heavyChain[len(heavyChain)-1].NumberU64()
if shorterNum >= longerNum { if shorterNum >= longerNum {
return nil, nil, nil, fmt.Errorf("Test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum) return nil, nil, nil, fmt.Errorf("test is moot, heavyChain num (%v) must be lower than canon num (%v)", shorterNum, longerNum)
} }
return chain, longChain, heavyChain, nil return chain, longChain, heavyChain, nil
} }
@ -2551,7 +2584,7 @@ func TestTransactionIndices(t *testing.T) {
// Import all blocks into ancient db // Import all blocks into ancient db
l := uint64(0) l := uint64(0)
chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2577,7 +2610,7 @@ func TestTransactionIndices(t *testing.T) {
} }
gspec.MustCommit(ancientDb) gspec.MustCommit(ancientDb)
l := l l := l
chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) chain, err = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2603,7 +2636,7 @@ func TestTransactionIndices(t *testing.T) {
tails := []uint64{0, 67 /* 130 - 64 + 1 */, 100 /* 131 - 32 + 1 */, 69 /* 132 - 64 + 1 */, 0} tails := []uint64{0, 67 /* 130 - 64 + 1 */, 100 /* 131 - 32 + 1 */, 69 /* 132 - 64 + 1 */, 0}
for i, l := range limit { for i, l := range limit {
l := l l := l
chain, err = NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) chain, err = NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2678,7 +2711,7 @@ func TestSkipStaleTxIndicesInSnapSync(t *testing.T) {
// Import all blocks into ancient db, only HEAD-32 indices are kept. // Import all blocks into ancient db, only HEAD-32 indices are kept.
l := uint64(32) l := uint64(32)
chain, err := NewBlockChain(ancientDb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{}, nil, &l) chain, err := NewBlockChain(ancientDb, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, &l)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2704,7 +2737,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey) testBankAddress = crypto.PubkeyToAddress(testBankKey.PublicKey)
bankFunds = big.NewInt(100000000000000000) bankFunds = big.NewInt(100000000000000000)
gspec = Genesis{ gspec = &Genesis{
Config: params.TestChainConfig, Config: params.TestChainConfig,
Alloc: GenesisAlloc{ Alloc: GenesisAlloc{
testBankAddress: {Balance: bankFunds}, testBankAddress: {Balance: bankFunds},
@ -2742,7 +2775,7 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
b.Fatalf("failed to create tester chain: %v", err) b.Fatalf("failed to create tester chain: %v", err)
} }
@ -2753,7 +2786,6 @@ func benchmarkLargeNumberOfValueToNonexisting(b *testing.B, numTxs, numBlocks in
b.StopTimer() b.StopTimer()
if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks { if got := chain.CurrentBlock().Transactions().Len(); got != numTxs*numBlocks {
b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got) b.Fatalf("Transactions were not included, expected %d, got %d", numTxs*numBlocks, got)
} }
} }
} }
@ -2818,14 +2850,18 @@ func TestSideImportPrunedBlocks(t *testing.T) {
// Generate a canonical chain to act as the main dataset // Generate a canonical chain to act as the main dataset
engine := ethash.NewFaker() engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db) gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: params.TestChainConfig,
}
genesis := gspec.MustCommit(db)
// Generate and import the canonical chain // Generate and import the canonical chain
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil) blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil)
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -2919,7 +2955,7 @@ func TestDeleteCreateRevert(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3030,7 +3066,7 @@ func TestDeleteRecreateSlots(t *testing.T) {
// Import the canonical chain // Import the canonical chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{
Debug: true, Debug: true,
Tracer: logger.NewJSONLogger(nil, os.Stdout), Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil, nil) }, nil, nil)
@ -3110,7 +3146,7 @@ func TestDeleteRecreateAccount(t *testing.T) {
// Import the canonical chain // Import the canonical chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{
Debug: true, Debug: true,
Tracer: logger.NewJSONLogger(nil, os.Stdout), Tracer: logger.NewJSONLogger(nil, os.Stdout),
}, nil, nil) }, nil, nil)
@ -3283,7 +3319,7 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
// Import the canonical chain // Import the canonical chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{
//Debug: true, //Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout), //Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil, nil) }, nil, nil)
@ -3417,7 +3453,7 @@ func TestInitThenFailCreateContract(t *testing.T) {
// Import the canonical chain // Import the canonical chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{ chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{
//Debug: true, //Debug: true,
//Tracer: vm.NewJSONLogger(nil, os.Stdout), //Tracer: vm.NewJSONLogger(nil, os.Stdout),
}, nil, nil) }, nil, nil)
@ -3507,7 +3543,7 @@ func TestEIP2718Transition(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3522,7 +3558,6 @@ func TestEIP2718Transition(t *testing.T) {
vm.GasQuickStep*2 + params.WarmStorageReadCostEIP2929 + params.ColdSloadCostEIP2929 vm.GasQuickStep*2 + params.WarmStorageReadCostEIP2929 + params.ColdSloadCostEIP2929
if block.GasUsed() != expected { if block.GasUsed() != expected {
t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expected, block.GasUsed()) t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expected, block.GasUsed())
} }
} }
@ -3602,7 +3637,7 @@ func TestEIP1559Transition(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3709,7 +3744,7 @@ func TestSetCanonical(t *testing.T) {
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }
@ -3815,7 +3850,7 @@ func TestCanonicalHashMarker(t *testing.T) {
// Initialize test chain // Initialize test chain
diskdb := rawdb.NewMemoryDatabase() diskdb := rawdb.NewMemoryDatabase()
gspec.MustCommit(diskdb) gspec.MustCommit(diskdb)
chain, err := NewBlockChain(diskdb, nil, params.TestChainConfig, engine, vm.Config{}, nil, nil) chain, err := NewBlockChain(diskdb, nil, gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("failed to create tester chain: %v", err) t.Fatalf("failed to create tester chain: %v", err)
} }

View file

@ -75,7 +75,7 @@ func (b *BloomIndexer) Process(ctx context.Context, header *types.Header) error
// Commit implements core.ChainIndexerBackend, finalizing the bloom section and // Commit implements core.ChainIndexerBackend, finalizing the bloom section and
// writing it out into the database. // writing it out into the database.
func (b *BloomIndexer) Commit() error { func (b *BloomIndexer) Commit() error {
batch := b.db.NewBatch() batch := b.db.NewBatchWithSize((int(b.size) / 8) * types.BloomBitLength)
for i := 0; i < types.BloomBitLength; i++ { for i := 0; i < types.BloomBitLength; i++ {
bits, err := b.gen.Bitset(uint(i)) bits, err := b.gen.Bitset(uint(i))
if err != nil { if err != nil {

View file

@ -79,7 +79,7 @@ func ExampleGenerateChain() {
}) })
// Import the chain. This runs all block validation rules. // Import the chain. This runs all block validation rules.
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil, nil) blockchain, _ := NewBlockChain(db, nil, gspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer blockchain.Stop() defer blockchain.Stop()
if i, err := blockchain.InsertChain(chain); err != nil { if i, err := blockchain.InsertChain(chain); err != nil {

View file

@ -30,32 +30,45 @@ import (
// blocks based on their extradata fields. // blocks based on their extradata fields.
func TestDAOForkRangeExtradata(t *testing.T) { func TestDAOForkRangeExtradata(t *testing.T) {
forkBlock := big.NewInt(32) forkBlock := big.NewInt(32)
chainConfig := *params.NonActivatedConfig
chainConfig.HomesteadBlock = big.NewInt(0)
// Generate a common prefix for both pro-forkers and non-forkers // Generate a common prefix for both pro-forkers and non-forkers
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
gspec := &Genesis{BaseFee: big.NewInt(params.InitialBaseFee)} gspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: &chainConfig,
}
genesis := gspec.MustCommit(db) genesis := gspec.MustCommit(db)
prefix, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {}) prefix, _ := GenerateChain(&chainConfig, genesis, ethash.NewFaker(), db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
// Create the concurrent, conflicting two nodes // Create the concurrent, conflicting two nodes
proDb := rawdb.NewMemoryDatabase() proDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(proDb) proConf := *params.NonActivatedConfig
proConf.HomesteadBlock = big.NewInt(0)
proConf := *params.TestChainConfig
proConf.DAOForkBlock = forkBlock proConf.DAOForkBlock = forkBlock
proConf.DAOForkSupport = true proConf.DAOForkSupport = true
progspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: &proConf,
}
gspec.MustCommit(proDb)
proBc, _ := NewBlockChain(proDb, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil) proBc, _ := NewBlockChain(proDb, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer proBc.Stop() defer proBc.Stop()
conDb := rawdb.NewMemoryDatabase() conDb := rawdb.NewMemoryDatabase()
gspec.MustCommit(conDb) conConf := *params.NonActivatedConfig
conConf.HomesteadBlock = big.NewInt(0)
conConf := *params.TestChainConfig
conConf.DAOForkBlock = forkBlock conConf.DAOForkBlock = forkBlock
conConf.DAOForkSupport = false conConf.DAOForkSupport = false
congspec := &Genesis{
BaseFee: big.NewInt(params.InitialBaseFee),
Config: &conConf,
}
gspec.MustCommit(conDb)
conBc, _ := NewBlockChain(conDb, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil) conBc, _ := NewBlockChain(conDb, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer conBc.Stop() defer conBc.Stop()
if _, err := proBc.InsertChain(prefix); err != nil { if _, err := proBc.InsertChain(prefix); err != nil {
@ -68,8 +81,8 @@ func TestDAOForkRangeExtradata(t *testing.T) {
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ { for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
// Create a pro-fork block, and try to feed into the no-fork chain // Create a pro-fork block, and try to feed into the no-fork chain
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) congspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil) bc, _ := NewBlockChain(db, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop() defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@ -93,8 +106,8 @@ func TestDAOForkRangeExtradata(t *testing.T) {
} }
// Create a no-fork block, and try to feed into the pro-fork chain // Create a no-fork block, and try to feed into the pro-fork chain
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) progspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil) bc, _ = NewBlockChain(db, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop() defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))
@ -119,8 +132,8 @@ func TestDAOForkRangeExtradata(t *testing.T) {
} }
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes // Verify that contra-forkers accept pro-fork extra-datas after forking finishes
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) congspec.MustCommit(db)
bc, _ := NewBlockChain(db, nil, &conConf, ethash.NewFaker(), vm.Config{}, nil, nil) bc, _ := NewBlockChain(db, nil, congspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop() defer bc.Stop()
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64())) blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()))
@ -139,8 +152,8 @@ func TestDAOForkRangeExtradata(t *testing.T) {
} }
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes // Verify that pro-forkers accept contra-fork extra-datas after forking finishes
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
gspec.MustCommit(db) progspec.MustCommit(db)
bc, _ = NewBlockChain(db, nil, &proConf, ethash.NewFaker(), vm.Config{}, nil, nil) bc, _ = NewBlockChain(db, nil, progspec, nil, ethash.NewFaker(), vm.Config{}, nil, nil)
defer bc.Stop() defer bc.Stop()
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64())) blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()))

View file

@ -91,7 +91,7 @@ var (
ErrFeeCapVeryHigh = errors.New("max fee per gas higher than 2^256-1") ErrFeeCapVeryHigh = errors.New("max fee per gas higher than 2^256-1")
// ErrFeeCapTooLow is returned if the transaction fee cap is less than the // ErrFeeCapTooLow is returned if the transaction fee cap is less than the
// the base fee of the block. // base fee of the block.
ErrFeeCapTooLow = errors.New("max fee per gas less than block base fee") ErrFeeCapTooLow = errors.New("max fee per gas less than block base fee")
// ErrSenderNoEOA is returned if the sender of a transaction is a contract. // ErrSenderNoEOA is returned if the sender of a transaction is a contract.

View file

@ -138,6 +138,16 @@ func TestCreation(t *testing.T) {
{6000000, ID{Hash: checksumToBytes(0xB8C6299D), Next: 0}}, // Future London block {6000000, ID{Hash: checksumToBytes(0xB8C6299D), Next: 0}}, // Future London block
}, },
}, },
// Sepolia test cases
{
params.SepoliaChainConfig,
params.SepoliaGenesisHash,
[]testcase{
{0, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Unsynced, last Frontier, Homestead, Tangerine, Spurious, Byzantium, Constantinople, Petersburg, Istanbul, Berlin and first London block
{1735370, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last London block
{1735371, ID{Hash: checksumToBytes(0xb96cbd13), Next: 0}}, // First MergeNetsplit block
},
},
// Merge test cases // Merge test cases
{ {
&mergeConfig, &mergeConfig,

View file

@ -80,10 +80,12 @@ func (ga *GenesisAlloc) UnmarshalJSON(data []byte) error {
return nil return nil
} }
// flush adds allocated genesis accounts into a fresh new statedb and // deriveHash computes the state root according to the genesis specification.
// commit the state changes into the given database handler. func (ga *GenesisAlloc) deriveHash() (common.Hash, error) {
func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) { // Create an ephemeral in-memory database for computing hash,
statedb, err := state.New(common.Hash{}, state.NewDatabase(db), nil) // all the derived states will be discarded to not pollute disk.
db := state.NewDatabase(rawdb.NewMemoryDatabase())
statedb, err := state.New(common.Hash{}, db, nil)
if err != nil { if err != nil {
return common.Hash{}, err return common.Hash{}, err
} }
@ -95,25 +97,39 @@ func (ga *GenesisAlloc) flush(db ethdb.Database) (common.Hash, error) {
statedb.SetState(addr, key, value) statedb.SetState(addr, key, value)
} }
} }
return statedb.Commit(false)
}
// 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) error {
statedb, err := state.New(common.Hash{}, state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true}), nil)
if err != nil {
return err
}
for addr, account := range *ga {
statedb.AddBalance(addr, account.Balance)
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
for key, value := range account.Storage {
statedb.SetState(addr, key, value)
}
}
root, err := statedb.Commit(false) root, err := statedb.Commit(false)
if err != nil { if err != nil {
return common.Hash{}, err return err
} }
err = statedb.Database().TrieDB().Commit(root, true, nil) err = statedb.Database().TrieDB().Commit(root, true, nil)
if err != nil { if err != nil {
return common.Hash{}, err return err
} }
return root, nil // Marshal the genesis state specification and persist.
}
// write writes the json marshaled genesis state into database
// with the given block hash as the unique identifier.
func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error {
blob, err := json.Marshal(ga) blob, err := json.Marshal(ga)
if err != nil { if err != nil {
return err return err
} }
rawdb.WriteGenesisState(db, hash, blob) rawdb.WriteGenesisStateSpec(db, root, blob)
return nil return nil
} }
@ -121,7 +137,7 @@ func (ga *GenesisAlloc) write(db ethdb.KeyValueWriter, hash common.Hash) error {
// hash and commits them into the given database handler. // hash and commits them into the given database handler.
func CommitGenesisState(db ethdb.Database, hash common.Hash) error { func CommitGenesisState(db ethdb.Database, hash common.Hash) error {
var alloc GenesisAlloc var alloc GenesisAlloc
blob := rawdb.ReadGenesisState(db, hash) blob := rawdb.ReadGenesisStateSpec(db, hash)
if len(blob) != 0 { if len(blob) != 0 {
if err := alloc.UnmarshalJSON(blob); err != nil { if err := alloc.UnmarshalJSON(blob); err != nil {
return err return err
@ -151,8 +167,7 @@ func CommitGenesisState(db ethdb.Database, hash common.Hash) error {
return errors.New("not found") return errors.New("not found")
} }
} }
_, err := alloc.flush(db) return alloc.flush(db)
return err
} }
// GenesisAccount is an account in the state of the genesis block. // GenesisAccount is an account in the state of the genesis block.
@ -196,7 +211,6 @@ func (h *storageJSON) UnmarshalText(text []byte) error {
} }
offset := len(h) - len(text)/2 // pad on the left offset := len(h) - len(text)/2 // pad on the left
if _, err := hex.Decode(h[offset:], text); err != nil { if _, err := hex.Decode(h[offset:], text); err != nil {
fmt.Println(err)
return fmt.Errorf("invalid hex storage key/value %q", text) return fmt.Errorf("invalid hex storage key/value %q", text)
} }
return nil return nil
@ -216,6 +230,12 @@ func (e *GenesisMismatchError) Error() string {
return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New) return fmt.Sprintf("database contains incompatible genesis (have %x, new %x)", e.Stored, e.New)
} }
// ChainOverrides contains the changes to chain config.
type ChainOverrides struct {
OverrideTerminalTotalDifficulty *big.Int
OverrideTerminalTotalDifficultyPassed *bool
}
// SetupGenesisBlock writes or updates the genesis block in db. // SetupGenesisBlock writes or updates the genesis block in db.
// The block that will be used is: // The block that will be used is:
// //
@ -230,21 +250,21 @@ func (e *GenesisMismatchError) Error() string {
// //
// The returned chain configuration is never nil. // The returned chain configuration is never nil.
func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) { func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
return SetupGenesisBlockWithOverride(db, genesis, nil, nil) return SetupGenesisBlockWithOverride(db, genesis, nil)
} }
func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrideGrayGlacier, overrideTerminalTotalDifficulty *big.Int) (*params.ChainConfig, common.Hash, error) { func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, overrides *ChainOverrides) (*params.ChainConfig, common.Hash, error) {
if genesis != nil && genesis.Config == nil { if genesis != nil && genesis.Config == nil {
return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig return params.AllEthashProtocolChanges, common.Hash{}, errGenesisNoConfig
} }
applyOverrides := func(config *params.ChainConfig) { applyOverrides := func(config *params.ChainConfig) {
if config != nil { if config != nil {
if overrideTerminalTotalDifficulty != nil { if overrides != nil && overrides.OverrideTerminalTotalDifficulty != nil {
config.TerminalTotalDifficulty = overrideTerminalTotalDifficulty config.TerminalTotalDifficulty = overrides.OverrideTerminalTotalDifficulty
} }
if overrideGrayGlacier != nil { if overrides != nil && overrides.OverrideTerminalTotalDifficultyPassed != nil {
config.GrayGlacierBlock = overrideGrayGlacier config.TerminalTotalDifficultyPassed = *overrides.OverrideTerminalTotalDifficultyPassed
} }
} }
} }
@ -273,7 +293,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
genesis = DefaultGenesisBlock() genesis = DefaultGenesisBlock()
} }
// Ensure the stored genesis matches with the given one. // Ensure the stored genesis matches with the given one.
hash := genesis.ToBlock(nil).Hash() hash := genesis.ToBlock().Hash()
if hash != stored { if hash != stored {
return genesis.Config, hash, &GenesisMismatchError{stored, hash} return genesis.Config, hash, &GenesisMismatchError{stored, hash}
} }
@ -286,7 +306,7 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
} }
// Check whether the genesis block is already written. // Check whether the genesis block is already written.
if genesis != nil { if genesis != nil {
hash := genesis.ToBlock(nil).Hash() hash := genesis.ToBlock().Hash()
if hash != stored { if hash != stored {
return genesis.Config, hash, &GenesisMismatchError{stored, hash} return genesis.Config, hash, &GenesisMismatchError{stored, hash}
} }
@ -326,6 +346,42 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, genesis *Genesis, override
return newcfg, stored, nil return newcfg, stored, nil
} }
// LoadCliqueConfig loads the stored clique config if the chain config
// is already present in database, otherwise, return the config in the
// provided genesis specification. Note the returned clique config can
// be nil if we are not in the clique network.
func LoadCliqueConfig(db ethdb.Database, genesis *Genesis) (*params.CliqueConfig, error) {
// Load the stored chain config from the database. It can be nil
// in case the database is empty. Notably, we only care about the
// chain config corresponds to the canonical chain.
stored := rawdb.ReadCanonicalHash(db, 0)
if stored != (common.Hash{}) {
storedcfg := rawdb.ReadChainConfig(db, stored)
if storedcfg != nil {
return storedcfg.Clique, nil
}
}
// Load the clique config from the provided genesis specification.
if genesis != nil {
// Reject invalid genesis spec without valid chain config
if genesis.Config == nil {
return nil, errGenesisNoConfig
}
// If the canonical genesis header is present, but the chain
// config is missing(initialize the empty leveldb with an
// external ancient chain segment), ensure the provided genesis
// is matched.
if stored != (common.Hash{}) && genesis.ToBlock().Hash() != stored {
return nil, &GenesisMismatchError{stored, genesis.ToBlock().Hash()}
}
return genesis.Config.Clique, nil
}
// There is no stored chain config and no new config provided,
// In this case the default chain config(mainnet) will be used,
// namely ethash is the specified consensus engine, return nil.
return nil, nil
}
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
switch { switch {
case g != nil: case g != nil:
@ -347,13 +403,9 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
} }
} }
// ToBlock creates the genesis block and writes state of a genesis specification // ToBlock returns the genesis block according to genesis specification.
// to the given database (or discards it if nil). func (g *Genesis) ToBlock() *types.Block {
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { root, err := g.Alloc.deriveHash()
if db == nil {
db = rawdb.NewMemoryDatabase()
}
root, err := g.Alloc.flush(db)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -390,7 +442,7 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
// Commit writes the block and state of a genesis specification to the database. // Commit writes the block and state of a genesis specification to the database.
// The block is committed as the canonical head block. // The block is committed as the canonical head block.
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) { func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
block := g.ToBlock(db) block := g.ToBlock()
if block.Number().Sign() != 0 { if block.Number().Sign() != 0 {
return nil, errors.New("can't commit genesis block with number > 0") return nil, errors.New("can't commit genesis block with number > 0")
} }
@ -404,7 +456,10 @@ func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength { if config.Clique != nil && len(block.Extra()) < 32+crypto.SignatureLength {
return nil, errors.New("can't start clique chain without signers") return nil, errors.New("can't start clique chain without signers")
} }
if err := g.Alloc.write(db, block.Hash()); err != nil { // 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); err != nil {
return nil, err return nil, err
} }
rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty()) rawdb.WriteTd(db, block.Hash(), block.NumberU64(), block.Difficulty())
@ -428,15 +483,6 @@ func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
return block return block
} }
// GenesisBlockForTesting creates and writes a block in which addr has the given wei balance.
func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
g := Genesis{
Alloc: GenesisAlloc{addr: {Balance: balance}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
return g.MustCommit(db)
}
// DefaultGenesisBlock returns the Ethereum main net genesis block. // DefaultGenesisBlock returns the Ethereum main net genesis block.
func DefaultGenesisBlock() *Genesis { func DefaultGenesisBlock() *Genesis {
return &Genesis{ return &Genesis{
@ -498,6 +544,7 @@ func DefaultSepoliaGenesisBlock() *Genesis {
} }
} }
// DefaultKilnGenesisBlock returns the kiln network genesis block.
func DefaultKilnGenesisBlock() *Genesis { func DefaultKilnGenesisBlock() *Genesis {
g := new(Genesis) g := new(Genesis)
reader := strings.NewReader(KilnAllocData) reader := strings.NewReader(KilnAllocData)

File diff suppressed because one or more lines are too long

View file

@ -117,7 +117,7 @@ func TestSetupGenesis(t *testing.T) {
// Advance to block #4, past the homestead transition block of customg. // Advance to block #4, past the homestead transition block of customg.
genesis := oldcustomg.MustCommit(db) genesis := oldcustomg.MustCommit(db)
bc, _ := NewBlockChain(db, nil, oldcustomg.Config, ethash.NewFullFaker(), vm.Config{}, nil, nil) bc, _ := NewBlockChain(db, nil, &oldcustomg, nil, ethash.NewFullFaker(), vm.Config{}, nil, nil)
defer bc.Stop() defer bc.Stop()
blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil) blocks, _ := GenerateChain(oldcustomg.Config, genesis, ethash.NewFaker(), db, 4, nil)
@ -178,7 +178,7 @@ func TestGenesisHashes(t *testing.T) {
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
} }
// Test via ToBlock // Test via ToBlock
if have := c.genesis.ToBlock(nil).Hash(); have != c.want { if have := c.genesis.ToBlock().Hash(); have != c.want {
t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex()) t.Errorf("case: %d a), want: %s, got: %s", i, c.want.Hex(), have.Hex())
} }
} }
@ -192,11 +192,7 @@ func TestGenesis_Commit(t *testing.T) {
} }
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
genesisBlock, err := genesis.Commit(db) genesisBlock := genesis.MustCommit(db)
if err != nil {
t.Fatal(err)
}
if genesis.Difficulty != nil { if genesis.Difficulty != nil {
t.Fatalf("assumption wrong") t.Fatalf("assumption wrong")
} }
@ -221,12 +217,12 @@ func TestReadWriteGenesisAlloc(t *testing.T) {
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
{2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}}, {2}: {Balance: big.NewInt(2), Storage: map[common.Hash]common.Hash{{2}: {2}}},
} }
hash = common.HexToHash("0xdeadbeef") hash, _ = alloc.deriveHash()
) )
alloc.write(db, hash) alloc.flush(db)
var reload GenesisAlloc var reload GenesisAlloc
err := reload.UnmarshalJSON(rawdb.ReadGenesisState(db, hash)) err := reload.UnmarshalJSON(rawdb.ReadGenesisStateSpec(db, hash))
if err != nil { if err != nil {
t.Fatalf("Failed to load genesis state %v", err) t.Fatalf("Failed to load genesis state %v", err)
} }

View file

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

View file

@ -285,7 +285,7 @@ func TestTdStorage(t *testing.T) {
func TestCanonicalMappingStorage(t *testing.T) { func TestCanonicalMappingStorage(t *testing.T) {
db := NewMemoryDatabase() db := NewMemoryDatabase()
// Create a test canonical number and assinged hash to move around // Create a test canonical number and assigned hash to move around
hash, number := common.Hash{0: 0xff}, uint64(314) hash, number := common.Hash{0: 0xff}, uint64(314)
if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) { if entry := ReadCanonicalHash(db, number); entry != (common.Hash{}) {
t.Fatalf("Non existent canonical mapping returned: %v", entry) t.Fatalf("Non existent canonical mapping returned: %v", entry)

View file

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

View file

@ -0,0 +1,86 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package rawdb
import "fmt"
// The list of table names of chain freezer.
const (
// chainFreezerHeaderTable indicates the name of the freezer header table.
chainFreezerHeaderTable = "headers"
// chainFreezerHashTable indicates the name of the freezer canonical hash table.
chainFreezerHashTable = "hashes"
// chainFreezerBodiesTable indicates the name of the freezer block body table.
chainFreezerBodiesTable = "bodies"
// chainFreezerReceiptTable indicates the name of the freezer receipts table.
chainFreezerReceiptTable = "receipts"
// 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,
}
// The list of identifiers of ancient stores.
var (
chainFreezerName = "chain" // the folder name of chain segment ancient store.
)
// freezers the collections of all builtin freezers.
var freezers = []string{chainFreezerName}
// InspectFreezerTable dumps out the index of a specific freezer table. The passed
// ancient indicates the path of root ancient directory where the chain freezer can
// be opened. Start and end specify the range for dumping out indexes.
// Note this function can only be used for debugging purposes.
func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error {
var (
path string
tables map[string]bool
)
switch freezerName {
case chainFreezerName:
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
default:
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
}
noSnappy, exist := tables[tableName]
if !exist {
var names []string
for name := range tables {
names = append(names, name)
}
return fmt.Errorf("unknown table, supported ones: %v", names)
}
table, err := newFreezerTable(path, tableName, noSnappy, true)
if err != nil {
return err
}
table.dumpIndexStdout(start, end)
return nil
}

View file

@ -241,7 +241,7 @@ func (f *chainFreezer) freeze(db ethdb.KeyValueStore) {
if n := len(ancients); n > 0 { if n := len(ancients); n > 0 {
context = append(context, []interface{}{"hash", ancients[n-1]}...) context = append(context, []interface{}{"hash", ancients[n-1]}...)
} }
log.Info("Deep froze chain segment", context...) log.Debug("Deep froze chain segment", context...)
// Avoid database thrashing with tiny writes // Avoid database thrashing with tiny writes
if frozen-first < freezerBatchLimit { if frozen-first < freezerBatchLimit {
@ -278,19 +278,19 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
} }
// Write to the batch. // Write to the batch.
if err := op.AppendRaw(freezerHashTable, number, hash[:]); err != nil { if err := op.AppendRaw(chainFreezerHashTable, number, hash[:]); err != nil {
return fmt.Errorf("can't write hash to Freezer: %v", err) return fmt.Errorf("can't write hash to Freezer: %v", err)
} }
if err := op.AppendRaw(freezerHeaderTable, number, header); err != nil { if err := op.AppendRaw(chainFreezerHeaderTable, number, header); err != nil {
return fmt.Errorf("can't write header to Freezer: %v", err) return fmt.Errorf("can't write header to Freezer: %v", err)
} }
if err := op.AppendRaw(freezerBodiesTable, number, body); err != nil { if err := op.AppendRaw(chainFreezerBodiesTable, number, body); err != nil {
return fmt.Errorf("can't write body to Freezer: %v", err) return fmt.Errorf("can't write body to Freezer: %v", err)
} }
if err := op.AppendRaw(freezerReceiptTable, number, receipts); err != nil { if err := op.AppendRaw(chainFreezerReceiptTable, number, receipts); err != nil {
return fmt.Errorf("can't write receipts to Freezer: %v", err) return fmt.Errorf("can't write receipts to Freezer: %v", err)
} }
if err := op.AppendRaw(freezerDifficultyTable, number, td); err != nil { if err := op.AppendRaw(chainFreezerDifficultyTable, number, td); err != nil {
return fmt.Errorf("can't write td to Freezer: %v", err) return fmt.Errorf("can't write td to Freezer: %v", err)
} }

View file

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

View file

@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"path"
"sync/atomic" "sync/atomic"
"time" "time"
@ -34,10 +35,16 @@ import (
// freezerdb is a database wrapper that enabled freezer data retrievals. // freezerdb is a database wrapper that enabled freezer data retrievals.
type freezerdb struct { type freezerdb struct {
ancientRoot string
ethdb.KeyValueStore ethdb.KeyValueStore
ethdb.AncientStore ethdb.AncientStore
} }
// AncientDatadir returns the path of root ancient directory.
func (frdb *freezerdb) AncientDatadir() (string, error) {
return frdb.ancientRoot, nil
}
// Close implements io.Closer, closing both the fast key-value store as well as // Close implements io.Closer, closing both the fast key-value store as well as
// the slow ancient tables. // the slow ancient tables.
func (frdb *freezerdb) Close() error { func (frdb *freezerdb) Close() error {
@ -162,12 +169,36 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
return &nofreezedb{KeyValueStore: db} return &nofreezedb{KeyValueStore: db}
} }
// resolveChainFreezerDir is a helper function which resolves the absolute path
// of chain freezer by considering backward compatibility.
func resolveChainFreezerDir(ancient string) string {
// Check if the chain freezer is already present in the specified
// sub folder, if not then two possibilities:
// - chain freezer is not initialized
// - chain freezer exists in legacy location (root ancient folder)
freezer := path.Join(ancient, chainFreezerName)
if !common.FileExist(freezer) {
if !common.FileExist(ancient) {
// The entire ancient store is not initialized, still use the sub
// folder for initialization.
} else {
// Ancient root is already initialized, then we hold the assumption
// that chain freezer is also initialized and located in root folder.
// In this case fallback to legacy location.
freezer = ancient
log.Info("Found legacy ancient chain path", "location", ancient)
}
}
return freezer
}
// NewDatabaseWithFreezer creates a high level database on top of a given key- // NewDatabaseWithFreezer creates a high level database on top of a given key-
// value data store with a freezer moving immutable chain segments into cold // value data store with a freezer moving immutable chain segments into cold
// storage. // storage. The passed ancient indicates the path of root ancient directory
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly bool) (ethdb.Database, error) { // 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 // Create the idle freezer instance
frdb, err := newChainFreezer(freezer, namespace, readonly, freezerTableSize, FreezerNoSnappy) frdb, err := newChainFreezer(resolveChainFreezerDir(ancient), namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -198,7 +229,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
// If the freezer already contains something, ensure that the genesis blocks // If the freezer already contains something, ensure that the genesis blocks
// match, otherwise we might mix up freezers across chains and destroy both // match, otherwise we might mix up freezers across chains and destroy both
// the freezer and the key-value store. // the freezer and the key-value store.
frgenesis, err := frdb.Ancient(freezerHashTable, 0) frgenesis, err := frdb.Ancient(chainFreezerHashTable, 0)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err) return nil, fmt.Errorf("failed to retrieve genesis from ancient %v", err)
} else if !bytes.Equal(kvgenesis, frgenesis) { } else if !bytes.Equal(kvgenesis, frgenesis) {
@ -229,7 +260,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 { if kvblob, _ := db.Get(headerHashKey(1)); len(kvblob) == 0 {
return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path") return nil, errors.New("ancient chain segments already extracted, please set --datadir.ancient to the correct path")
} }
// Block #1 is still in the database, we're allowed to init a new feezer // Block #1 is still in the database, we're allowed to init a new freezer
} }
// Otherwise, the head header is still the genesis, we're allowed to init a new // Otherwise, the head header is still the genesis, we're allowed to init a new
// freezer. // freezer.
@ -244,6 +275,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
}() }()
} }
return &freezerdb{ return &freezerdb{
ancientRoot: ancient,
KeyValueStore: db, KeyValueStore: db,
AncientStore: frdb, AncientStore: frdb,
}, nil }, nil
@ -273,13 +305,15 @@ func NewLevelDBDatabase(file string, cache int, handles int, namespace string, r
} }
// NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a // NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a
// freezer moving immutable chain segments into cold storage. // freezer moving immutable chain segments into cold storage. The passed ancient
func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string, readonly bool) (ethdb.Database, error) { // indicates the path of root ancient directory where the chain freezer can be
// opened.
func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, ancient string, namespace string, readonly bool) (ethdb.Database, error) {
kvdb, err := leveldb.New(file, cache, handles, namespace, readonly) kvdb, err := leveldb.New(file, cache, handles, namespace, readonly)
if err != nil { if err != nil {
return nil, err return nil, err
} }
frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace, readonly) frdb, err := NewDatabaseWithFreezer(kvdb, ancient, namespace, readonly)
if err != nil { if err != nil {
kvdb.Close() kvdb.Close()
return nil, err return nil, err
@ -441,7 +475,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
} }
// Inspect append-only file store then. // Inspect append-only file store then.
ancientSizes := []*common.StorageSize{&ancientHeadersSize, &ancientBodiesSize, &ancientReceiptsSize, &ancientHashesSize, &ancientTdsSize} ancientSizes := []*common.StorageSize{&ancientHeadersSize, &ancientBodiesSize, &ancientReceiptsSize, &ancientHashesSize, &ancientTdsSize}
for i, category := range []string{freezerHeaderTable, freezerBodiesTable, freezerReceiptTable, freezerHashTable, freezerDifficultyTable} { for i, category := range []string{chainFreezerHeaderTable, chainFreezerBodiesTable, chainFreezerReceiptTable, chainFreezerHashTable, chainFreezerDifficultyTable} {
if size, err := db.AncientSize(category); err == nil { if size, err := db.AncientSize(category); err == nil {
*ancientSizes[i] += common.StorageSize(size) *ancientSizes[i] += common.StorageSize(size)
total += common.StorageSize(size) total += common.StorageSize(size)

View file

@ -68,8 +68,6 @@ type Freezer struct {
frozen uint64 // Number of blocks already frozen frozen uint64 // Number of blocks already frozen
tail uint64 // Number of the first stored item in the freezer tail uint64 // Number of the first stored item in the freezer
datadir string // Path of root directory of ancient store
// This lock synchronizes writers and the truncate operation, as well as // This lock synchronizes writers and the truncate operation, as well as
// the "atomic" (batched) read operations. // the "atomic" (batched) read operations.
writeLock sync.RWMutex writeLock sync.RWMutex
@ -111,7 +109,6 @@ func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize ui
readonly: readonly, readonly: readonly,
tables: make(map[string]*freezerTable), tables: make(map[string]*freezerTable),
instanceLock: lock, instanceLock: lock,
datadir: datadir,
} }
// Create the tables. // Create the tables.
@ -429,7 +426,7 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
// Set up new dir for the migrated table, the content of which // Set up new dir for the migrated table, the content of which
// we'll at the end move over to the ancients dir. // we'll at the end move over to the ancients dir.
migrationPath := filepath.Join(ancientsPath, "migration") migrationPath := filepath.Join(ancientsPath, "migration")
newTable, err := NewFreezerTable(migrationPath, kind, table.noCompression, false) newTable, err := newFreezerTable(migrationPath, kind, table.noCompression, false)
if err != nil { if err != nil {
return err return err
} }
@ -486,11 +483,5 @@ func (f *Freezer) MigrateTable(kind string, convert convertLegacyFn) error {
if err := os.Remove(migrationPath); err != nil { if err := os.Remove(migrationPath); err != nil {
return err return err
} }
return nil return nil
} }
// AncientDatadir returns the root directory path of the ancient store.
func (f *Freezer) AncientDatadir() (string, error) {
return f.datadir, nil
}

View file

@ -123,8 +123,8 @@ type freezerTable struct {
lock sync.RWMutex // Mutex protecting the data file descriptors lock sync.RWMutex // Mutex protecting the data file descriptors
} }
// NewFreezerTable opens the given path as a freezer table. // newFreezerTable opens the given path as a freezer table.
func NewFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) { func newFreezerTable(path, name string, disableSnappy, readonly bool) (*freezerTable, error) {
return newTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, readonly) return newTable(path, name, metrics.NilMeter{}, metrics.NilMeter{}, metrics.NilGauge{}, freezerTableSize, disableSnappy, readonly)
} }
@ -884,9 +884,7 @@ func (t *freezerTable) Sync() error {
return t.head.Sync() return t.head.Sync()
} }
// DumpIndex is a debug print utility function, mainly for testing. It can also func (t *freezerTable) dumpIndexStdout(start, stop int64) {
// be used to analyse a live freezer table index.
func (t *freezerTable) DumpIndex(start, stop int64) {
t.dumpIndex(os.Stdout, start, stop) t.dumpIndex(os.Stdout, start, stop)
} }

View file

@ -902,7 +902,7 @@ func TestSequentialRead(t *testing.T) {
} }
// Write 15 bytes 30 times // Write 15 bytes 30 times
writeChunks(t, f, 30, 15) writeChunks(t, f, 30, 15)
f.DumpIndex(0, 30) f.dumpIndexStdout(0, 30)
f.Close() f.Close()
} }
{ // Open it, iterate, verify iteration { // Open it, iterate, verify iteration

View file

@ -111,33 +111,6 @@ var (
preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil) preimageHitCounter = metrics.NewRegisteredCounter("db/preimage/hits", nil)
) )
const (
// freezerHeaderTable indicates the name of the freezer header table.
freezerHeaderTable = "headers"
// freezerHashTable indicates the name of the freezer canonical hash table.
freezerHashTable = "hashes"
// freezerBodiesTable indicates the name of the freezer block body table.
freezerBodiesTable = "bodies"
// freezerReceiptTable indicates the name of the freezer receipts table.
freezerReceiptTable = "receipts"
// freezerDifficultyTable indicates the name of the freezer total difficulty table.
freezerDifficultyTable = "diffs"
)
// FreezerNoSnappy configures whether compression is disabled for the ancient-tables.
// Hashes and difficulties don't compress well.
var FreezerNoSnappy = map[string]bool{
freezerHeaderTable: false,
freezerHashTable: true,
freezerBodiesTable: false,
freezerReceiptTable: false,
freezerDifficultyTable: true,
}
// LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary // LegacyTxLookupEntry is the legacy TxLookupEntry definition with some unnecessary
// fields. // fields.
type LegacyTxLookupEntry struct { type LegacyTxLookupEntry struct {
@ -247,7 +220,7 @@ func configKey(hash common.Hash) []byte {
return append(configPrefix, hash.Bytes()...) return append(configPrefix, hash.Bytes()...)
} }
// genesisKey = genesisPrefix + hash // genesisStateSpecKey = genesisPrefix + hash
func genesisKey(hash common.Hash) []byte { func genesisStateSpecKey(hash common.Hash) []byte {
return append(genesisPrefix, hash.Bytes()...) return append(genesisPrefix, hash.Bytes()...)
} }

View file

@ -63,7 +63,7 @@ type Trie interface {
// GetKey returns the sha3 preimage of a hashed key that was previously used // GetKey returns the sha3 preimage of a hashed key that was previously used
// to store a value. // to store a value.
// //
// TODO(fjl): remove this when SecureTrie is removed // TODO(fjl): remove this when StateTrie is removed
GetKey([]byte) []byte GetKey([]byte) []byte
// TryGet returns the value for key stored in the trie. The value bytes must // TryGet returns the value for key stored in the trie. The value bytes must
@ -71,8 +71,8 @@ type Trie interface {
// trie.MissingNodeError is returned. // trie.MissingNodeError is returned.
TryGet(key []byte) ([]byte, error) TryGet(key []byte) ([]byte, error)
// TryUpdateAccount abstract an account write in the trie. // TryGetAccount abstract an account read from the trie.
TryUpdateAccount(key []byte, account *types.StateAccount) error TryGetAccount(key []byte) (*types.StateAccount, error)
// TryUpdate associates key with value in the trie. If value has length zero, any // TryUpdate associates key with value in the trie. If value has length zero, any
// existing value is deleted from the trie. The value bytes must not be modified // existing value is deleted from the trie. The value bytes must not be modified
@ -80,17 +80,27 @@ type Trie interface {
// database, a trie.MissingNodeError is returned. // database, a trie.MissingNodeError is returned.
TryUpdate(key, value []byte) error TryUpdate(key, value []byte) error
// TryUpdateAccount abstract an account write to the trie.
TryUpdateAccount(key []byte, account *types.StateAccount) error
// TryDelete removes any existing value for key from the trie. If a node was not // TryDelete removes any existing value for key from the trie. If a node was not
// found in the database, a trie.MissingNodeError is returned. // found in the database, a trie.MissingNodeError is returned.
TryDelete(key []byte) error TryDelete(key []byte) error
// TryDeleteAccount abstracts an account deletion from the trie.
TryDeleteAccount(key []byte) error
// Hash returns the root hash of the trie. It does not write to the database and // Hash returns the root hash of the trie. It does not write to the database and
// can be used even if the trie doesn't have one. // can be used even if the trie doesn't have one.
Hash() common.Hash Hash() common.Hash
// Commit writes all nodes to the trie's memory database, tracking the internal // Commit collects all dirty nodes in the trie and replace them with the
// and external (for account tries) references. // corresponding node hash. All collected nodes(including dirty leaves if
Commit(onleaf trie.LeafCallback) (common.Hash, int, error) // collectLeaf is true) will be encapsulated into a nodeset for return.
// The returned nodeset can be nil if the trie is clean(nothing to commit).
// Once the trie is committed, it's not usable anymore. A new trie must
// be created with new root and updated trie database for following usage
Commit(collectLeaf bool) (common.Hash, *trie.NodeSet, error)
// NodeIterator returns an iterator that returns nodes of the trie. Iteration // NodeIterator returns an iterator that returns nodes of the trie. Iteration
// starts at the key after the given start key. // starts at the key after the given start key.
@ -133,7 +143,7 @@ type cachingDB struct {
// OpenTrie opens the main account trie at a specific root hash. // OpenTrie opens the main account trie at a specific root hash.
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
tr, err := trie.NewSecure(common.Hash{}, root, db.db) tr, err := trie.NewStateTrie(common.Hash{}, root, db.db)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -142,7 +152,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
// OpenStorageTrie opens the storage trie of an account. // OpenStorageTrie opens the storage trie of an account.
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
tr, err := trie.NewSecure(addrHash, root, db.db) tr, err := trie.NewStateTrie(addrHash, root, db.db)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -152,7 +162,7 @@ func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
// CopyTrie returns an independent copy of the given trie. // CopyTrie returns an independent copy of the given trie.
func (db *cachingDB) CopyTrie(t Trie) Trie { func (db *cachingDB) CopyTrie(t Trie) Trie {
switch t := t.(type) { switch t := t.(type) {
case *trie.SecureTrie: case *trie.StateTrie:
return t.Copy() return t.Copy()
default: default:
panic(fmt.Errorf("unknown trie type %T", t)) panic(fmt.Errorf("unknown trie type %T", t))

Some files were not shown because too many files have changed in this diff Show more