mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +00:00
Merge branch 'ethereum:master' into master
This commit is contained in:
commit
d6a2c62fb6
338 changed files with 4608 additions and 3891 deletions
|
|
@ -28,9 +28,10 @@ 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
|
||||||
# - contextcheck
|
# - contextcheck
|
||||||
# - errchkjson # lots of false positives
|
# - errchkjson # lots of false positives
|
||||||
# - errorlint # this check crashes
|
# - errorlint # this check crashes
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
## Go Ethereum
|
## Go Ethereum
|
||||||
|
|
||||||
Official Golang implementation of the Ethereum protocol.
|
Official Golang execution layer implementation of the Ethereum protocol.
|
||||||
|
|
||||||
[ 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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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},
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 == "" {
|
||||||
|
|
|
||||||
|
|
@ -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"`
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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},
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
34
build/ci.go
34
build/ci.go
|
|
@ -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],
|
||||||
|
|
|
||||||
|
|
@ -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")) {
|
||||||
|
|
|
||||||
|
|
@ -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, ðapi.SignTransactionResult{Raw: rlpdata, Tx: &tx})
|
add("OnApproved - SignTransactionResult", desc, ðapi.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)",
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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: ð.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: ð.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: ð.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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 := ð.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 := ð.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: ð.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(ð.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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
|
|
@ -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: ð.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 := ð.GetBlockHeadersPacket66{
|
req1 := &GetBlockHeaders{
|
||||||
RequestId: uint64(111),
|
RequestId: uint64(111),
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
||||||
Origin: eth.HashOrNumber{
|
Origin: eth.HashOrNumber{
|
||||||
|
|
@ -259,7 +159,7 @@ func (s *Suite) TestSimultaneousRequests66(t *utesting.T) {
|
||||||
Reverse: false,
|
Reverse: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
req2 := ð.GetBlockHeadersPacket66{
|
req2 := &GetBlockHeaders{
|
||||||
RequestId: uint64(222),
|
RequestId: uint64(222),
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersPacket: ð.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 := ð.GetBlockHeadersPacket66{
|
request1 := &GetBlockHeaders{
|
||||||
RequestId: reqID,
|
RequestId: reqID,
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
||||||
Origin: eth.HashOrNumber{
|
Origin: eth.HashOrNumber{
|
||||||
|
|
@ -328,7 +231,7 @@ func (s *Suite) TestSameRequestID66(t *utesting.T) {
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
request2 := ð.GetBlockHeadersPacket66{
|
request2 := &GetBlockHeaders{
|
||||||
RequestId: reqID,
|
RequestId: reqID,
|
||||||
GetBlockHeadersPacket: ð.GetBlockHeadersPacket{
|
GetBlockHeadersPacket: ð.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: ð.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 := ð.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 := ð.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
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,12 +109,7 @@ 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.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)...)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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`,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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{
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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++ {
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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, ðashConf, nil, false, chainDb)
|
engine := ethconfig.CreateConsensusEngine(stack, ðashConfig, 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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 (
|
||||||
|
|
|
||||||
|
|
@ -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"`
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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()))
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
133
core/genesis.go
133
core/genesis.go
|
|
@ -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
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
86
core/rawdb/ancient_scheme.go
Normal file
86
core/rawdb/ancient_scheme.go
Normal 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
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ var (
|
||||||
errNotSupported = errors.New("this operation is not supported")
|
errNotSupported = errors.New("this operation is not supported")
|
||||||
)
|
)
|
||||||
|
|
||||||
// indexEntry contains the number/id of the file that the data resides in, aswell as the
|
// indexEntry contains the number/id of the file that the data resides in, as well as the
|
||||||
// offset within the file to the end of the data.
|
// offset within the file to the end of the data.
|
||||||
// In serialized form, the filenum is stored as uint16.
|
// In serialized form, the filenum is stored as uint16.
|
||||||
type indexEntry struct {
|
type indexEntry struct {
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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()...)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Reference in a new issue