forked from cerc-io/plugeth
Merge pull request #3794 from fjl/core-genesis-refactor
core: refactor genesis handling
This commit is contained in:
commit
8771c3061f
@ -37,9 +37,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
)
|
||||
|
||||
// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
|
||||
var chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), EIP150Block: new(big.Int), EIP158Block: new(big.Int)}
|
||||
|
||||
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
|
||||
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
|
||||
|
||||
@ -60,11 +57,12 @@ type SimulatedBackend struct {
|
||||
|
||||
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
|
||||
// for testing purposes.
|
||||
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
|
||||
func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
|
||||
database, _ := ethdb.NewMemDatabase()
|
||||
core.WriteGenesisBlockForTesting(database, accounts...)
|
||||
blockchain, _ := core.NewBlockChain(database, chainConfig, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
backend := &SimulatedBackend{database: database, blockchain: blockchain}
|
||||
genesis := core.Genesis{Config: params.AllProtocolChanges, Alloc: alloc}
|
||||
genesis.MustCommit(database)
|
||||
blockchain, _ := core.NewBlockChain(database, genesis.Config, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
backend := &SimulatedBackend{database: database, blockchain: blockchain, config: genesis.Config}
|
||||
backend.rollback()
|
||||
return backend
|
||||
}
|
||||
@ -90,7 +88,7 @@ func (b *SimulatedBackend) Rollback() {
|
||||
}
|
||||
|
||||
func (b *SimulatedBackend) rollback() {
|
||||
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
|
||||
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
|
||||
b.pendingBlock = blocks[0]
|
||||
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
|
||||
}
|
||||
@ -253,7 +251,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
|
||||
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain)
|
||||
// Create a new environment which holds all relevant information
|
||||
// about the transaction and calling mechanisms.
|
||||
vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{})
|
||||
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
|
||||
gaspool := new(core.GasPool).AddGas(math.MaxBig256)
|
||||
ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
|
||||
return ret, gasUsed, err
|
||||
@ -274,7 +272,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
|
||||
panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
|
||||
}
|
||||
|
||||
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
|
||||
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
|
||||
for _, tx := range b.pendingBlock.Transactions() {
|
||||
block.AddTx(tx)
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy an interaction tester contract and call a transaction on it
|
||||
_, _, interactor, err := DeployInteractor(auth, sim, "Deploy string")
|
||||
@ -210,7 +210,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy a tuple tester contract and execute a structured call on it
|
||||
_, _, getter, err := DeployGetter(auth, sim)
|
||||
@ -242,7 +242,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy a tuple tester contract and execute a structured call on it
|
||||
_, _, tupler, err := DeployTupler(auth, sim)
|
||||
@ -284,7 +284,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy a slice tester contract and execute a n array call on it
|
||||
_, _, slicer, err := DeploySlicer(auth, sim)
|
||||
@ -318,7 +318,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy a default method invoker contract and execute its default method
|
||||
_, _, defaulter, err := DeployDefaulter(auth, sim)
|
||||
@ -351,7 +351,7 @@ var bindTests = []struct {
|
||||
`[{"constant":true,"inputs":[],"name":"String","outputs":[{"name":"","type":"string"}],"type":"function"}]`,
|
||||
`
|
||||
// Create a simulator and wrap a non-deployed contract
|
||||
sim := backends.NewSimulatedBackend()
|
||||
sim := backends.NewSimulatedBackend(nil)
|
||||
|
||||
nonexistent, err := NewNonExistent(common.Address{}, sim)
|
||||
if err != nil {
|
||||
@ -387,7 +387,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy a funky gas pattern contract
|
||||
_, _, limiter, err := DeployFunkyGasPattern(auth, sim)
|
||||
@ -423,7 +423,7 @@ var bindTests = []struct {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
|
||||
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
|
||||
|
||||
// Deploy a sender tester contract and execute a structured call on it
|
||||
_, _, callfrom, err := DeployCallFrom(auth, sim)
|
||||
@ -458,7 +458,7 @@ func TestBindings(t *testing.T) {
|
||||
t.Skip("go sdk not found for testing")
|
||||
}
|
||||
// Skip the test if the go-ethereum sources are symlinked (https://github.com/golang/go/issues/14845)
|
||||
linkTestCode := fmt.Sprintf("package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend())\n}")
|
||||
linkTestCode := fmt.Sprintf("package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend(nil))\n}")
|
||||
linkTestDeps, err := imports.Process("", []byte(linkTestCode), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("failed check for goimports symlink bug: %v", err)
|
||||
|
@ -53,9 +53,8 @@ var waitDeployedTests = map[string]struct {
|
||||
|
||||
func TestWaitDeployed(t *testing.T) {
|
||||
for name, test := range waitDeployedTests {
|
||||
backend := backends.NewSimulatedBackend(core.GenesisAccount{
|
||||
Address: crypto.PubkeyToAddress(testKey.PublicKey),
|
||||
Balance: big.NewInt(10000000000),
|
||||
backend := backends.NewSimulatedBackend(core.GenesisAlloc{
|
||||
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
|
||||
})
|
||||
|
||||
// Create the transaction.
|
||||
|
@ -17,6 +17,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
@ -110,17 +111,22 @@ func initGenesis(ctx *cli.Context) error {
|
||||
stack := makeFullNode(ctx)
|
||||
chaindb := utils.MakeChainDatabase(ctx, stack)
|
||||
|
||||
genesisFile, err := os.Open(genesisPath)
|
||||
file, err := os.Open(genesisPath)
|
||||
if err != nil {
|
||||
utils.Fatalf("failed to read genesis file: %v", err)
|
||||
}
|
||||
defer genesisFile.Close()
|
||||
defer file.Close()
|
||||
|
||||
block, err := core.WriteGenesisBlock(chaindb, genesisFile)
|
||||
genesis := new(core.Genesis)
|
||||
if err := json.NewDecoder(file).Decode(genesis); err != nil {
|
||||
utils.Fatalf("invalid genesis file: %v", err)
|
||||
}
|
||||
|
||||
_, hash, err := core.SetupGenesisBlock(chaindb, genesis)
|
||||
if err != nil {
|
||||
utils.Fatalf("failed to write genesis block: %v", err)
|
||||
}
|
||||
log.Info("Successfully wrote genesis state", "hash", block.Hash())
|
||||
log.Info("Successfully wrote genesis state", "hash", hash)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -786,7 +786,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||
|
||||
ethConf := ð.Config{
|
||||
Etherbase: MakeEtherbase(ks, ctx),
|
||||
ChainConfig: MakeChainConfig(ctx, stack),
|
||||
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
|
||||
LightMode: ctx.GlobalBool(LightModeFlag.Name),
|
||||
LightServ: ctx.GlobalInt(LightServFlag.Name),
|
||||
@ -822,7 +821,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
|
||||
ethConf.NetworkId = 3
|
||||
}
|
||||
ethConf.Genesis = core.DefaultTestnetGenesisBlock()
|
||||
|
||||
case ctx.GlobalBool(DevModeFlag.Name):
|
||||
ethConf.Genesis = core.DevGenesisBlock()
|
||||
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
|
||||
@ -884,67 +882,6 @@ func SetupNetwork(ctx *cli.Context) {
|
||||
params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name))
|
||||
}
|
||||
|
||||
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
|
||||
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *params.ChainConfig {
|
||||
db := MakeChainDatabase(ctx, stack)
|
||||
defer db.Close()
|
||||
|
||||
return MakeChainConfigFromDb(ctx, db)
|
||||
}
|
||||
|
||||
// MakeChainConfigFromDb reads the chain configuration from the given database.
|
||||
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *params.ChainConfig {
|
||||
// If the chain is already initialized, use any existing chain configs
|
||||
config := new(params.ChainConfig)
|
||||
|
||||
genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0)
|
||||
if genesis != nil {
|
||||
storedConfig, err := core.GetChainConfig(db, genesis.Hash())
|
||||
switch err {
|
||||
case nil:
|
||||
config = storedConfig
|
||||
case core.ChainConfigNotFoundErr:
|
||||
// No configs found, use empty, will populate below
|
||||
default:
|
||||
Fatalf("Could not make chain configuration: %v", err)
|
||||
}
|
||||
}
|
||||
// set chain id in case it's zero.
|
||||
if config.ChainId == nil {
|
||||
config.ChainId = new(big.Int)
|
||||
}
|
||||
// Check whether we are allowed to set default config params or not:
|
||||
// - If no genesis is set, we're running either mainnet or testnet (private nets use `geth init`)
|
||||
// - If a genesis is already set, ensure we have a configuration for it (mainnet or testnet)
|
||||
defaults := genesis == nil ||
|
||||
(genesis.Hash() == params.MainNetGenesisHash && !ctx.GlobalBool(TestNetFlag.Name)) ||
|
||||
(genesis.Hash() == params.TestNetGenesisHash && ctx.GlobalBool(TestNetFlag.Name))
|
||||
|
||||
if defaults {
|
||||
if ctx.GlobalBool(TestNetFlag.Name) {
|
||||
config = params.TestnetChainConfig
|
||||
} else if ctx.GlobalBool(DevModeFlag.Name) {
|
||||
config = params.AllProtocolChanges
|
||||
} else {
|
||||
// Homestead fork
|
||||
config.HomesteadBlock = params.MainNetHomesteadBlock
|
||||
// DAO fork
|
||||
config.DAOForkBlock = params.MainNetDAOForkBlock
|
||||
config.DAOForkSupport = true
|
||||
|
||||
// DoS reprice fork
|
||||
config.EIP150Block = params.MainNetHomesteadGasRepriceBlock
|
||||
config.EIP150Hash = params.MainNetHomesteadGasRepriceHash
|
||||
|
||||
// DoS state cleanup fork
|
||||
config.EIP155Block = params.MainNetSpuriousDragon
|
||||
config.EIP158Block = params.MainNetSpuriousDragon
|
||||
config.ChainId = params.MainNetChainID
|
||||
}
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
func ChainDbName(ctx *cli.Context) string {
|
||||
if ctx.GlobalBool(LightModeFlag.Name) {
|
||||
return "lightchaindata"
|
||||
@ -968,26 +905,34 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
|
||||
return chainDb
|
||||
}
|
||||
|
||||
func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
||||
var genesis *core.Genesis
|
||||
switch {
|
||||
case ctx.GlobalBool(TestNetFlag.Name):
|
||||
genesis = core.DefaultTestnetGenesisBlock()
|
||||
case ctx.GlobalBool(DevModeFlag.Name):
|
||||
genesis = core.DevGenesisBlock()
|
||||
}
|
||||
return genesis
|
||||
}
|
||||
|
||||
// MakeChain creates a chain manager from set command line flags.
|
||||
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
|
||||
var err error
|
||||
chainDb = MakeChainDatabase(ctx, stack)
|
||||
|
||||
if ctx.GlobalBool(TestNetFlag.Name) {
|
||||
_, err := core.WriteTestNetGenesisBlock(chainDb)
|
||||
if err != nil {
|
||||
Fatalf("Failed to write testnet genesis: %v", err)
|
||||
}
|
||||
}
|
||||
chainConfig := MakeChainConfigFromDb(ctx, chainDb)
|
||||
|
||||
seal := pow.PoW(pow.FakePow{})
|
||||
if !ctx.GlobalBool(FakePoWFlag.Name) {
|
||||
seal = pow.NewFullEthash("", 1, 0, "", 1, 0)
|
||||
}
|
||||
chain, err = core.NewBlockChain(chainDb, chainConfig, seal, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)})
|
||||
config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
|
||||
if err != nil {
|
||||
Fatalf("Could not start chainmanager: %v", err)
|
||||
Fatalf("%v", err)
|
||||
}
|
||||
vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
|
||||
chain, err = core.NewBlockChain(chainDb, config, seal, new(event.TypeMux), vmcfg)
|
||||
if err != nil {
|
||||
Fatalf("Can't create BlockChain: %v", err)
|
||||
}
|
||||
return chain, chainDb
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func (b *Bytes) UnmarshalJSON(input []byte) error {
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (b *Bytes) UnmarshalText(input []byte) error {
|
||||
raw, err := checkText(input)
|
||||
raw, err := checkText(input, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -73,7 +73,28 @@ func (b Bytes) String() string {
|
||||
// determines the required input length. This function is commonly used to implement the
|
||||
// UnmarshalText method for fixed-size types.
|
||||
func UnmarshalFixedText(typname string, input, out []byte) error {
|
||||
raw, err := checkText(input)
|
||||
raw, err := checkText(input, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(raw)/2 != len(out) {
|
||||
return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
|
||||
}
|
||||
// Pre-verify syntax before modifying out.
|
||||
for _, b := range raw {
|
||||
if decodeNibble(b) == badNibble {
|
||||
return ErrSyntax
|
||||
}
|
||||
}
|
||||
hex.Decode(out, raw)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
|
||||
// length of out determines the required input length. This function is commonly used to
|
||||
// implement the UnmarshalText method for fixed-size types.
|
||||
func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
|
||||
raw, err := checkText(input, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -243,14 +264,15 @@ func bytesHave0xPrefix(input []byte) bool {
|
||||
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
|
||||
}
|
||||
|
||||
func checkText(input []byte) ([]byte, error) {
|
||||
func checkText(input []byte, wantPrefix bool) ([]byte, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, nil // empty strings are allowed
|
||||
}
|
||||
if !bytesHave0xPrefix(input) {
|
||||
if bytesHave0xPrefix(input) {
|
||||
input = input[2:]
|
||||
} else if wantPrefix {
|
||||
return nil, ErrMissingPrefix
|
||||
}
|
||||
input = input[2:]
|
||||
if len(input)%2 != 0 {
|
||||
return nil, ErrOddLength
|
||||
}
|
||||
|
@ -337,3 +337,38 @@ func TestUnmarshalUint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalFixedUnprefixedText(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
want []byte
|
||||
wantErr error
|
||||
}{
|
||||
{input: "0x2", wantErr: ErrOddLength},
|
||||
{input: "2", wantErr: ErrOddLength},
|
||||
{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
|
||||
{input: "4444", wantErr: errors.New("hex string has length 4, want 8 for x")},
|
||||
// check that output is not modified for partially correct input
|
||||
{input: "444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
|
||||
{input: "0x444444gg", wantErr: ErrSyntax, want: []byte{0, 0, 0, 0}},
|
||||
// valid inputs
|
||||
{input: "44444444", want: []byte{0x44, 0x44, 0x44, 0x44}},
|
||||
{input: "0x44444444", want: []byte{0x44, 0x44, 0x44, 0x44}},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
out := make([]byte, 4)
|
||||
err := UnmarshalFixedUnprefixedText("x", []byte(test.input), out)
|
||||
switch {
|
||||
case err == nil && test.wantErr != nil:
|
||||
t.Errorf("%q: got no error, expected %q", test.input, test.wantErr)
|
||||
case err != nil && test.wantErr == nil:
|
||||
t.Errorf("%q: unexpected error %q", test.input, err)
|
||||
case err != nil && err.Error() != test.wantErr.Error():
|
||||
t.Errorf("%q: error mismatch: got %q, want %q", test.input, err, test.wantErr)
|
||||
}
|
||||
if test.want != nil && !bytes.Equal(out, test.want) {
|
||||
t.Errorf("%q: output mismatch: got %x, want %x", test.input, out, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package math
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
@ -35,6 +36,24 @@ const (
|
||||
wordBytes = wordBits / 8
|
||||
)
|
||||
|
||||
// HexOrDecimal256 marshals big.Int as hex or decimal.
|
||||
type HexOrDecimal256 big.Int
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (i *HexOrDecimal256) UnmarshalText(input []byte) error {
|
||||
bigint, ok := ParseBig256(string(input))
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid hex or decimal integer %q", input)
|
||||
}
|
||||
*i = HexOrDecimal256(*bigint)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler.
|
||||
func (i *HexOrDecimal256) MarshalText() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("%#x", (*big.Int)(i))), nil
|
||||
}
|
||||
|
||||
// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax.
|
||||
// Leading zeros are accepted. The empty string parses as zero.
|
||||
func ParseBig256(s string) (*big.Int, bool) {
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseBig256(t *testing.T) {
|
||||
func TestHexOrDecimal256(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
num *big.Int
|
||||
@ -47,13 +47,14 @@ func TestParseBig256(t *testing.T) {
|
||||
{"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
num, ok := ParseBig256(test.input)
|
||||
if ok != test.ok {
|
||||
t.Errorf("ParseBig(%q) -> ok = %t, want %t", test.input, ok, test.ok)
|
||||
var num HexOrDecimal256
|
||||
err := num.UnmarshalText([]byte(test.input))
|
||||
if (err == nil) != test.ok {
|
||||
t.Errorf("ParseBig(%q) -> (err == nil) == %t, want %t", test.input, err == nil, test.ok)
|
||||
continue
|
||||
}
|
||||
if num != nil && test.num != nil && num.Cmp(test.num) != 0 {
|
||||
t.Errorf("ParseBig(%q) -> %d, want %d", test.input, num, test.num)
|
||||
if test.num != nil && (*big.Int)(&num).Cmp(test.num) != 0 {
|
||||
t.Errorf("ParseBig(%q) -> %d, want %d", test.input, (*big.Int)(&num), test.num)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
package math
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
// Integer limit values.
|
||||
@ -34,6 +37,24 @@ const (
|
||||
MaxUint64 = 1<<64 - 1
|
||||
)
|
||||
|
||||
// HexOrDecimal64 marshals uint64 as hex or decimal.
|
||||
type HexOrDecimal64 uint64
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (i *HexOrDecimal64) UnmarshalText(input []byte) error {
|
||||
int, ok := ParseUint64(string(input))
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid hex or decimal integer %q", input)
|
||||
}
|
||||
*i = HexOrDecimal64(int)
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler.
|
||||
func (i HexOrDecimal64) MarshalText() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("%#x", uint64(i))), nil
|
||||
}
|
||||
|
||||
// ParseUint64 parses s as an integer in decimal or hexadecimal syntax.
|
||||
// Leading zeros are accepted. The empty string parses as zero.
|
||||
func ParseUint64(s string) (uint64, bool) {
|
||||
|
@ -65,7 +65,7 @@ func TestOverflow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseUint64(t *testing.T) {
|
||||
func TestHexOrDecimal64(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
num uint64
|
||||
@ -88,12 +88,13 @@ func TestParseUint64(t *testing.T) {
|
||||
{"18446744073709551617", 0, false},
|
||||
}
|
||||
for _, test := range tests {
|
||||
num, ok := ParseUint64(test.input)
|
||||
if ok != test.ok {
|
||||
t.Errorf("ParseUint64(%q) -> ok = %t, want %t", test.input, ok, test.ok)
|
||||
var num HexOrDecimal64
|
||||
err := num.UnmarshalText([]byte(test.input))
|
||||
if (err == nil) != test.ok {
|
||||
t.Errorf("ParseUint64(%q) -> (err == nil) = %t, want %t", test.input, err == nil, test.ok)
|
||||
continue
|
||||
}
|
||||
if ok && num != test.num {
|
||||
if err == nil && uint64(num) != test.num {
|
||||
t.Errorf("ParseUint64(%q) -> %d, want %d", test.input, num, test.num)
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
@ -30,13 +31,8 @@ const (
|
||||
AddressLength = 20
|
||||
)
|
||||
|
||||
type (
|
||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||
Hash [HashLength]byte
|
||||
|
||||
// Address represents the 20 byte address of an Ethereum account.
|
||||
Address [AddressLength]byte
|
||||
)
|
||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||
type Hash [HashLength]byte
|
||||
|
||||
func BytesToHash(b []byte) Hash {
|
||||
var h Hash
|
||||
@ -113,7 +109,24 @@ func EmptyHash(h Hash) bool {
|
||||
return h == Hash{}
|
||||
}
|
||||
|
||||
// UnprefixedHash allows marshaling a Hash without 0x prefix.
|
||||
type UnprefixedHash Hash
|
||||
|
||||
// UnmarshalText decodes the hash from hex. The 0x prefix is optional.
|
||||
func (h *UnprefixedHash) UnmarshalText(input []byte) error {
|
||||
return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:])
|
||||
}
|
||||
|
||||
// MarshalText encodes the hash as hex.
|
||||
func (h UnprefixedHash) MarshalText() ([]byte, error) {
|
||||
return []byte(hex.EncodeToString(h[:])), nil
|
||||
}
|
||||
|
||||
/////////// Address
|
||||
|
||||
// Address represents the 20 byte address of an Ethereum account.
|
||||
type Address [AddressLength]byte
|
||||
|
||||
func BytesToAddress(b []byte) Address {
|
||||
var a Address
|
||||
a.SetBytes(b)
|
||||
@ -181,12 +194,15 @@ func (a *Address) UnmarshalText(input []byte) error {
|
||||
return hexutil.UnmarshalFixedText("Address", input, a[:])
|
||||
}
|
||||
|
||||
// PP Pretty Prints a byte slice in the following format:
|
||||
// hex(value[:4])...(hex[len(value)-4:])
|
||||
func PP(value []byte) string {
|
||||
if len(value) <= 8 {
|
||||
return Bytes2Hex(value)
|
||||
}
|
||||
// UnprefixedHash allows marshaling an Address without 0x prefix.
|
||||
type UnprefixedAddress Address
|
||||
|
||||
return fmt.Sprintf("%x...%x", value[:4], value[len(value)-4])
|
||||
// UnmarshalText decodes the address from hex. The 0x prefix is optional.
|
||||
func (a *UnprefixedAddress) UnmarshalText(input []byte) error {
|
||||
return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:])
|
||||
}
|
||||
|
||||
// MarshalText encodes the address as hex.
|
||||
func (a UnprefixedAddress) MarshalText() ([]byte, error) {
|
||||
return []byte(hex.EncodeToString(a[:])), nil
|
||||
}
|
||||
|
@ -21,17 +21,16 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -97,7 +96,7 @@ func newTester(t *testing.T, confOverride func(*eth.Config)) *tester {
|
||||
t.Fatalf("failed to create node: %v", err)
|
||||
}
|
||||
ethConf := ð.Config{
|
||||
ChainConfig: ¶ms.ChainConfig{HomesteadBlock: new(big.Int), ChainId: new(big.Int)},
|
||||
Genesis: core.DevGenesisBlock(),
|
||||
Etherbase: common.HexToAddress(testAddress),
|
||||
PowTest: true,
|
||||
}
|
||||
|
@ -42,11 +42,11 @@ var (
|
||||
)
|
||||
|
||||
func newTestBackend() *backends.SimulatedBackend {
|
||||
return backends.NewSimulatedBackend(
|
||||
core.GenesisAccount{Address: addr0, Balance: big.NewInt(1000000000)},
|
||||
core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000000)},
|
||||
core.GenesisAccount{Address: addr2, Balance: big.NewInt(1000000000)},
|
||||
)
|
||||
return backends.NewSimulatedBackend(core.GenesisAlloc{
|
||||
addr0: {Balance: big.NewInt(1000000000)},
|
||||
addr1: {Balance: big.NewInt(1000000000)},
|
||||
addr2: {Balance: big.NewInt(1000000000)},
|
||||
})
|
||||
}
|
||||
|
||||
func deploy(prvKey *ecdsa.PrivateKey, amount *big.Int, backend *backends.SimulatedBackend) (common.Address, error) {
|
||||
|
@ -34,7 +34,7 @@ var (
|
||||
)
|
||||
|
||||
func TestENS(t *testing.T) {
|
||||
contractBackend := backends.NewSimulatedBackend(core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000000)})
|
||||
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
|
||||
transactOpts := bind.NewKeyedTransactor(key)
|
||||
// Workaround for bug estimating gas in the call to Register
|
||||
transactOpts.GasLimit = big.NewInt(1000000)
|
||||
|
@ -35,11 +35,11 @@ func setupReleaseTest(t *testing.T, prefund ...*ecdsa.PrivateKey) (*ecdsa.Privat
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
|
||||
accounts := []core.GenesisAccount{{Address: auth.From, Balance: big.NewInt(10000000000)}}
|
||||
alloc := core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}
|
||||
for _, key := range prefund {
|
||||
accounts = append(accounts, core.GenesisAccount{Address: crypto.PubkeyToAddress(key.PublicKey), Balance: big.NewInt(10000000000)})
|
||||
alloc[crypto.PubkeyToAddress(key.PublicKey)] = core.GenesisAccount{Balance: big.NewInt(10000000000)}
|
||||
}
|
||||
sim := backends.NewSimulatedBackend(accounts...)
|
||||
sim := backends.NewSimulatedBackend(alloc)
|
||||
|
||||
// Deploy a version oracle contract, commit and return
|
||||
_, _, oracle, err := DeployReleaseOracle(auth, sim, []common.Address{auth.From})
|
||||
|
@ -166,13 +166,17 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||
|
||||
// Generate a chain of b.N blocks using the supplied block
|
||||
// generator function.
|
||||
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds})
|
||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, b.N, gen)
|
||||
gspec := Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: GenesisAlloc{benchRootAddr: {Balance: benchRootFunds}},
|
||||
}
|
||||
genesis := gspec.MustCommit(db)
|
||||
chain, _ := GenerateChain(gspec.Config, genesis, db, b.N, gen)
|
||||
|
||||
// Time the insertion of the new chain.
|
||||
// State and blocks are stored in the same DB.
|
||||
evmux := new(event.TypeMux)
|
||||
chainman, _ := NewBlockChain(db, ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, pow.FakePow{}, evmux, vm.Config{})
|
||||
chainman, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, evmux, vm.Config{})
|
||||
defer chainman.Stop()
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
@ -282,7 +286,7 @@ func benchReadChain(b *testing.B, full bool, count uint64) {
|
||||
if err != nil {
|
||||
b.Fatalf("error opening database at %v: %v", dir, err)
|
||||
}
|
||||
chain, err := NewBlockChain(db, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
chain, err := NewBlockChain(db, params.TestChainConfig, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
if err != nil {
|
||||
b.Fatalf("error creating chain: %v", err)
|
||||
}
|
||||
|
@ -17,51 +17,36 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
)
|
||||
|
||||
func testChainConfig() *params.ChainConfig {
|
||||
return params.TestChainConfig
|
||||
//return ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)}
|
||||
}
|
||||
|
||||
func proc() (Validator, *BlockChain) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
var mux event.TypeMux
|
||||
|
||||
WriteTestNetGenesisBlock(db)
|
||||
blockchain, err := NewBlockChain(db, testChainConfig(), pow.NewTestEthash(), &mux, vm.Config{})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
func testGenesis(account common.Address, balance *big.Int) *Genesis {
|
||||
return &Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: GenesisAlloc{account: {Balance: balance}},
|
||||
}
|
||||
return blockchain.validator, blockchain
|
||||
}
|
||||
|
||||
func TestNumber(t *testing.T) {
|
||||
_, chain := proc()
|
||||
|
||||
chain := newTestBlockChain()
|
||||
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
|
||||
cfg := testChainConfig()
|
||||
header := makeHeader(cfg, chain.Genesis(), statedb)
|
||||
header := makeHeader(chain.config, chain.Genesis(), statedb)
|
||||
header.Number = big.NewInt(3)
|
||||
err := ValidateHeader(cfg, pow.FakePow{}, header, chain.Genesis().Header(), false, false)
|
||||
err := ValidateHeader(chain.config, pow.FakePow{}, header, chain.Genesis().Header(), false, false)
|
||||
if err != BlockNumberErr {
|
||||
t.Errorf("expected block number error, got %q", err)
|
||||
}
|
||||
|
||||
header = makeHeader(cfg, chain.Genesis(), statedb)
|
||||
err = ValidateHeader(cfg, pow.FakePow{}, header, chain.Genesis().Header(), false, false)
|
||||
header = makeHeader(chain.config, chain.Genesis(), statedb)
|
||||
err = ValidateHeader(chain.config, pow.FakePow{}, header, chain.Genesis().Header(), false, false)
|
||||
if err == BlockNumberErr {
|
||||
t.Errorf("didn't expect block number error")
|
||||
}
|
||||
|
@ -20,10 +20,6 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -36,24 +32,21 @@ import (
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
||||
|
||||
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
|
||||
var eventMux event.TypeMux
|
||||
WriteTestNetGenesisBlock(db)
|
||||
blockchain, err := NewBlockChain(db, testChainConfig(), pow.NewTestEthash(), &eventMux, vm.Config{})
|
||||
if err != nil {
|
||||
t.Error("failed creating blockchain:", err)
|
||||
t.FailNow()
|
||||
return nil
|
||||
// newTestBlockChain creates a blockchain without validation.
|
||||
func newTestBlockChain() *BlockChain {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
gspec := &Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Difficulty: big.NewInt(1),
|
||||
}
|
||||
|
||||
gspec.MustCommit(db)
|
||||
blockchain, err := NewBlockChain(db, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
blockchain.SetValidator(bproc{})
|
||||
return blockchain
|
||||
}
|
||||
|
||||
@ -171,21 +164,6 @@ func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadChain(fn string, t *testing.T) (types.Blocks, error) {
|
||||
fh, err := os.OpenFile(filepath.Join("..", "_data", fn), os.O_RDONLY, os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fh.Close()
|
||||
|
||||
var chain types.Blocks
|
||||
if err := rlp.Decode(fh, &chain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return chain, nil
|
||||
}
|
||||
|
||||
func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) {
|
||||
_, err := blockchain.InsertChain(chain)
|
||||
if err != nil {
|
||||
@ -196,12 +174,10 @@ func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *
|
||||
}
|
||||
|
||||
func TestLastBlock(t *testing.T) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
|
||||
bchain := theBlockChain(db, t)
|
||||
block := makeBlockChain(bchain.CurrentBlock(), 1, db, 0)[0]
|
||||
bchain := newTestBlockChain()
|
||||
block := makeBlockChain(bchain.CurrentBlock(), 1, bchain.chainDb, 0)[0]
|
||||
bchain.insert(block)
|
||||
if block.Hash() != GetHeadBlockHash(db) {
|
||||
if block.Hash() != GetHeadBlockHash(bchain.chainDb) {
|
||||
t.Errorf("Write/Get HeadBlockHash failed")
|
||||
}
|
||||
}
|
||||
@ -340,88 +316,6 @@ func testBrokenChain(t *testing.T, full bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestChainInsertions(t *testing.T) {
|
||||
t.Skip("Skipped: outdated test files")
|
||||
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
|
||||
chain1, err := loadChain("valid1", t)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
chain2, err := loadChain("valid2", t)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
blockchain := theBlockChain(db, t)
|
||||
|
||||
const max = 2
|
||||
done := make(chan bool, max)
|
||||
|
||||
go insertChain(done, blockchain, chain1, t)
|
||||
go insertChain(done, blockchain, chain2, t)
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
if chain2[len(chain2)-1].Hash() != blockchain.CurrentBlock().Hash() {
|
||||
t.Error("chain2 is canonical and shouldn't be")
|
||||
}
|
||||
|
||||
if chain1[len(chain1)-1].Hash() != blockchain.CurrentBlock().Hash() {
|
||||
t.Error("chain1 isn't canonical and should be")
|
||||
}
|
||||
}
|
||||
|
||||
func TestChainMultipleInsertions(t *testing.T) {
|
||||
t.Skip("Skipped: outdated test files")
|
||||
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
|
||||
const max = 4
|
||||
chains := make([]types.Blocks, max)
|
||||
var longest int
|
||||
for i := 0; i < max; i++ {
|
||||
var err error
|
||||
name := "valid" + strconv.Itoa(i+1)
|
||||
chains[i], err = loadChain(name, t)
|
||||
if len(chains[i]) >= len(chains[longest]) {
|
||||
longest = i
|
||||
}
|
||||
fmt.Println("loaded", name, "with a length of", len(chains[i]))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
blockchain := theBlockChain(db, t)
|
||||
|
||||
done := make(chan bool, max)
|
||||
for i, chain := range chains {
|
||||
// XXX the go routine would otherwise reference the same (chain[3]) variable and fail
|
||||
i := i
|
||||
chain := chain
|
||||
go func() {
|
||||
insertChain(done, blockchain, chain, t)
|
||||
fmt.Println(i, "done")
|
||||
}()
|
||||
}
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
<-done
|
||||
}
|
||||
|
||||
if chains[longest][len(chains[longest])-1].Hash() != blockchain.CurrentBlock().Hash() {
|
||||
t.Error("Invalid canonical chain")
|
||||
}
|
||||
}
|
||||
|
||||
type bproc struct{}
|
||||
|
||||
func (bproc) ValidateBlock(*types.Block) error { return nil }
|
||||
@ -452,6 +346,7 @@ func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.B
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyRootHash,
|
||||
ReceiptHash: types.EmptyRootHash,
|
||||
Time: big.NewInt(int64(i) + 1),
|
||||
}
|
||||
if i == 0 {
|
||||
header.ParentHash = genesis.Hash()
|
||||
@ -464,29 +359,6 @@ func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.B
|
||||
return chain
|
||||
}
|
||||
|
||||
func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
|
||||
var eventMux event.TypeMux
|
||||
bc := &BlockChain{
|
||||
chainDb: db,
|
||||
genesisBlock: genesis,
|
||||
eventMux: &eventMux,
|
||||
pow: pow.FakePow{},
|
||||
config: testChainConfig(),
|
||||
}
|
||||
valFn := func() HeaderValidator { return bc.Validator() }
|
||||
bc.hc, _ = NewHeaderChain(db, testChainConfig(), valFn, bc.getProcInterrupt)
|
||||
bc.bodyCache, _ = lru.New(100)
|
||||
bc.bodyRLPCache, _ = lru.New(100)
|
||||
bc.blockCache, _ = lru.New(100)
|
||||
bc.futureBlocks, _ = lru.New(100)
|
||||
bc.badBlocks, _ = lru.New(10)
|
||||
bc.SetValidator(bproc{})
|
||||
bc.SetProcessor(bproc{})
|
||||
bc.ResetWithGenesisBlock(genesis)
|
||||
|
||||
return bc
|
||||
}
|
||||
|
||||
// Tests that reorganising a long difficult chain after a short easy one
|
||||
// overwrites the canonical numbers and links in the database.
|
||||
func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) }
|
||||
@ -506,18 +378,15 @@ func testReorgShort(t *testing.T, full bool) {
|
||||
}
|
||||
|
||||
func testReorg(t *testing.T, first, second []int, td int64, full bool) {
|
||||
// Create a pristine block chain
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||
bc := chm(genesis, db)
|
||||
bc := newTestBlockChain()
|
||||
|
||||
// Insert an easy and a difficult chain afterwards
|
||||
if full {
|
||||
bc.InsertChain(makeBlockChainWithDiff(genesis, first, 11))
|
||||
bc.InsertChain(makeBlockChainWithDiff(genesis, second, 22))
|
||||
bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, first, 11))
|
||||
bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, second, 22))
|
||||
} else {
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, first, 11), 1)
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, second, 22), 1)
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1)
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1)
|
||||
}
|
||||
// Check that the chain is valid number and link wise
|
||||
if full {
|
||||
@ -536,7 +405,7 @@ func testReorg(t *testing.T, first, second []int, td int64, full bool) {
|
||||
}
|
||||
}
|
||||
// Make sure the chain total difficulty is the correct one
|
||||
want := new(big.Int).Add(genesis.Difficulty(), big.NewInt(td))
|
||||
want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td))
|
||||
if full {
|
||||
if have := bc.GetTdByHash(bc.CurrentBlock().Hash()); have.Cmp(want) != 0 {
|
||||
t.Errorf("total difficulty mismatch: have %v, want %v", have, want)
|
||||
@ -553,19 +422,16 @@ func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) }
|
||||
func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) }
|
||||
|
||||
func testBadHashes(t *testing.T, full bool) {
|
||||
// Create a pristine block chain
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||
bc := chm(genesis, db)
|
||||
bc := newTestBlockChain()
|
||||
|
||||
// Create a chain, ban a hash and try to import
|
||||
var err error
|
||||
if full {
|
||||
blocks := makeBlockChainWithDiff(genesis, []int{1, 2, 4}, 10)
|
||||
blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
|
||||
BadHashes[blocks[2].Header().Hash()] = true
|
||||
_, err = bc.InsertChain(blocks)
|
||||
} else {
|
||||
headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 4}, 10)
|
||||
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
|
||||
BadHashes[headers[2].Hash()] = true
|
||||
_, err = bc.InsertHeaderChain(headers, 1)
|
||||
}
|
||||
@ -580,14 +446,11 @@ func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) }
|
||||
func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) }
|
||||
|
||||
func testReorgBadHashes(t *testing.T, full bool) {
|
||||
// Create a pristine block chain
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||
bc := chm(genesis, db)
|
||||
bc := newTestBlockChain()
|
||||
|
||||
// Create a chain, import and ban afterwards
|
||||
headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
|
||||
blocks := makeBlockChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
|
||||
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
|
||||
blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
|
||||
|
||||
if full {
|
||||
if _, err := bc.InsertChain(blocks); err != nil {
|
||||
@ -608,8 +471,9 @@ func testReorgBadHashes(t *testing.T, full bool) {
|
||||
BadHashes[headers[3].Hash()] = true
|
||||
defer func() { delete(BadHashes, headers[3].Hash()) }()
|
||||
}
|
||||
// Create a new chain manager and check it rolled back the state
|
||||
ncm, err := NewBlockChain(db, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
|
||||
// Create a new BlockChain and check that it rolled back the state.
|
||||
ncm, err := NewBlockChain(bc.chainDb, bc.config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create new chain manager: %v", err)
|
||||
}
|
||||
@ -663,7 +527,7 @@ func testInsertNonceError(t *testing.T, full bool) {
|
||||
failHash = headers[failAt].Hash()
|
||||
|
||||
blockchain.pow = failPow{failNum}
|
||||
blockchain.validator = NewBlockValidator(testChainConfig(), blockchain, failPow{failNum})
|
||||
blockchain.validator = NewBlockValidator(params.TestChainConfig, blockchain, failPow{failNum})
|
||||
|
||||
failRes, err = blockchain.InsertHeaderChain(headers, 1)
|
||||
}
|
||||
@ -705,10 +569,11 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
funds = big.NewInt(1000000000)
|
||||
genesis = GenesisBlockForTesting(gendb, address, funds)
|
||||
signer = types.NewEIP155Signer(big.NewInt(1))
|
||||
gspec = testGenesis(address, funds)
|
||||
genesis = gspec.MustCommit(gendb)
|
||||
signer = types.NewEIP155Signer(gspec.Config.ChainId)
|
||||
)
|
||||
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, gendb, 1024, func(i int, block *BlockGen) {
|
||||
blocks, receipts := GenerateChain(gspec.Config, genesis, gendb, 1024, func(i int, block *BlockGen) {
|
||||
block.SetCoinbase(common.Address{0x00})
|
||||
|
||||
// If the block number is multiple of 3, send a few bonus transactions to the miner
|
||||
@ -728,17 +593,17 @@ func TestFastVsFullChains(t *testing.T) {
|
||||
})
|
||||
// Import the chain as an archive node for the comparison baseline
|
||||
archiveDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||
|
||||
archive, _ := NewBlockChain(archiveDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
gspec.MustCommit(archiveDb)
|
||||
archive, _ := NewBlockChain(archiveDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
|
||||
if n, err := archive.InsertChain(blocks); err != nil {
|
||||
t.Fatalf("failed to process block %d: %v", n, err)
|
||||
}
|
||||
|
||||
// Fast import the chain as a non-archive node to test
|
||||
fastDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||
fast, _ := NewBlockChain(fastDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
gspec.MustCommit(fastDb)
|
||||
fast, _ := NewBlockChain(fastDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
|
||||
headers := make([]*types.Header, len(blocks))
|
||||
for i, block := range blocks {
|
||||
@ -788,10 +653,11 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
funds = big.NewInt(1000000000)
|
||||
genesis = GenesisBlockForTesting(gendb, address, funds)
|
||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
|
||||
genesis = gspec.MustCommit(gendb)
|
||||
)
|
||||
height := uint64(1024)
|
||||
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, gendb, int(height), nil)
|
||||
blocks, receipts := GenerateChain(gspec.Config, genesis, gendb, int(height), nil)
|
||||
|
||||
// Configure a subchain to roll back
|
||||
remove := []common.Hash{}
|
||||
@ -812,9 +678,9 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
}
|
||||
// Import the chain as an archive node and ensure all pointers are updated
|
||||
archiveDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
|
||||
gspec.MustCommit(archiveDb)
|
||||
|
||||
archive, _ := NewBlockChain(archiveDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
archive, _ := NewBlockChain(archiveDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
|
||||
if n, err := archive.InsertChain(blocks); err != nil {
|
||||
t.Fatalf("failed to process block %d: %v", n, err)
|
||||
@ -825,8 +691,8 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
|
||||
// Import the chain as a non-archive node and ensure all pointers are updated
|
||||
fastDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
|
||||
fast, _ := NewBlockChain(fastDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
gspec.MustCommit(fastDb)
|
||||
fast, _ := NewBlockChain(fastDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
|
||||
headers := make([]*types.Header, len(blocks))
|
||||
for i, block := range blocks {
|
||||
@ -844,8 +710,8 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
|
||||
// Import the chain as a light node and ensure all pointers are updated
|
||||
lightDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
|
||||
light, _ := NewBlockChain(lightDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
gspec.MustCommit(lightDb)
|
||||
light, _ := NewBlockChain(lightDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
|
||||
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
|
||||
t.Fatalf("failed to insert header %d: %v", n, err)
|
||||
@ -857,9 +723,6 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
|
||||
|
||||
// Tests that chain reorganisations handle transaction removals and reinsertions.
|
||||
func TestChainTxReorgs(t *testing.T) {
|
||||
params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
|
||||
params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
|
||||
|
||||
var (
|
||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||
@ -868,13 +731,19 @@ func TestChainTxReorgs(t *testing.T) {
|
||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
signer = types.NewEIP155Signer(big.NewInt(1))
|
||||
)
|
||||
genesis := WriteGenesisBlockForTesting(db,
|
||||
GenesisAccount{addr1, big.NewInt(1000000)},
|
||||
GenesisAccount{addr2, big.NewInt(1000000)},
|
||||
GenesisAccount{addr3, big.NewInt(1000000)},
|
||||
gspec = &Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
GasLimit: 3141592,
|
||||
Alloc: GenesisAlloc{
|
||||
addr1: {Balance: big.NewInt(1000000)},
|
||||
addr2: {Balance: big.NewInt(1000000)},
|
||||
addr3: {Balance: big.NewInt(1000000)},
|
||||
},
|
||||
}
|
||||
genesis = gspec.MustCommit(db)
|
||||
signer = types.NewEIP155Signer(gspec.Config.ChainId)
|
||||
)
|
||||
|
||||
// Create two transactions shared between the chains:
|
||||
// - postponed: transaction included at a later block in the forked chain
|
||||
// - swapped: transaction included at the same block number in the forked chain
|
||||
@ -892,7 +761,7 @@ func TestChainTxReorgs(t *testing.T) {
|
||||
// - futureAdd: transaction added after the reorg has already finished
|
||||
var pastAdd, freshAdd, futureAdd *types.Transaction
|
||||
|
||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {
|
||||
chain, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, gen *BlockGen) {
|
||||
switch i {
|
||||
case 0:
|
||||
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
|
||||
@ -911,13 +780,13 @@ func TestChainTxReorgs(t *testing.T) {
|
||||
})
|
||||
// Import the chain. This runs all block validation rules.
|
||||
evmux := &event.TypeMux{}
|
||||
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
|
||||
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, evmux, vm.Config{})
|
||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
|
||||
}
|
||||
|
||||
// overwrite the old chain
|
||||
chain, _ = GenerateChain(params.TestChainConfig, genesis, db, 5, func(i int, gen *BlockGen) {
|
||||
chain, _ = GenerateChain(gspec.Config, genesis, db, 5, func(i int, gen *BlockGen) {
|
||||
switch i {
|
||||
case 0:
|
||||
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
|
||||
@ -969,8 +838,6 @@ func TestChainTxReorgs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLogReorgs(t *testing.T) {
|
||||
params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
|
||||
params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
|
||||
|
||||
var (
|
||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
@ -978,14 +845,13 @@ func TestLogReorgs(t *testing.T) {
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
// this code generates a log
|
||||
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
|
||||
signer = types.NewEIP155Signer(big.NewInt(1))
|
||||
)
|
||||
genesis := WriteGenesisBlockForTesting(db,
|
||||
GenesisAccount{addr1, big.NewInt(10000000000000)},
|
||||
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
|
||||
genesis = gspec.MustCommit(db)
|
||||
signer = types.NewEIP155Signer(gspec.Config.ChainId)
|
||||
)
|
||||
|
||||
evmux := &event.TypeMux{}
|
||||
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
|
||||
var evmux event.TypeMux
|
||||
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, &evmux, vm.Config{})
|
||||
|
||||
subs := evmux.Subscribe(RemovedLogsEvent{})
|
||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
|
||||
@ -1017,19 +883,20 @@ func TestReorgSideEvent(t *testing.T) {
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
|
||||
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(10000000000000)})
|
||||
signer = types.NewEIP155Signer(big.NewInt(1))
|
||||
gspec = testGenesis(addr1, big.NewInt(10000000000000))
|
||||
genesis = gspec.MustCommit(db)
|
||||
signer = types.NewEIP155Signer(gspec.Config.ChainId)
|
||||
)
|
||||
|
||||
evmux := &event.TypeMux{}
|
||||
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
|
||||
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, evmux, vm.Config{})
|
||||
|
||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
|
||||
chain, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, gen *BlockGen) {})
|
||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||
t.Fatalf("failed to insert chain: %v", err)
|
||||
}
|
||||
|
||||
replacementBlocks, _ := GenerateChain(params.TestChainConfig, genesis, db, 4, func(i int, gen *BlockGen) {
|
||||
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, db, 4, func(i int, gen *BlockGen) {
|
||||
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1)
|
||||
if i == 2 {
|
||||
gen.OffsetTime(-1)
|
||||
@ -1092,28 +959,21 @@ done:
|
||||
|
||||
// Tests if the canonical block can be fetched from the database during chain insertion.
|
||||
func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||
var (
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
genesis = WriteGenesisBlockForTesting(db)
|
||||
)
|
||||
|
||||
evmux := &event.TypeMux{}
|
||||
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
|
||||
|
||||
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
|
||||
bc := newTestBlockChain()
|
||||
chain, _ := GenerateChain(bc.config, bc.genesisBlock, bc.chainDb, 10, func(i int, gen *BlockGen) {})
|
||||
|
||||
for i := range chain {
|
||||
go func(block *types.Block) {
|
||||
// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
|
||||
for {
|
||||
ch := GetCanonicalHash(db, block.NumberU64())
|
||||
ch := GetCanonicalHash(bc.chainDb, block.NumberU64())
|
||||
if ch == (common.Hash{}) {
|
||||
continue // busy wait for canonical hash to be written
|
||||
}
|
||||
if ch != block.Hash() {
|
||||
t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex())
|
||||
}
|
||||
fb := GetBlock(db, ch, block.NumberU64())
|
||||
fb := GetBlock(bc.chainDb, ch, block.NumberU64())
|
||||
if fb == nil {
|
||||
t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex())
|
||||
}
|
||||
@ -1124,7 +984,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
|
||||
}
|
||||
}(chain[i])
|
||||
|
||||
blockchain.InsertChain(types.Blocks{chain[i]})
|
||||
bc.InsertChain(types.Blocks{chain[i]})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1136,13 +996,16 @@ func TestEIP155Transition(t *testing.T) {
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
funds = big.NewInt(1000000000)
|
||||
deleteAddr = common.Address{1}
|
||||
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{address, funds}, GenesisAccount{deleteAddr, new(big.Int)})
|
||||
config = ¶ms.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
|
||||
gspec = &Genesis{
|
||||
Config: ¶ms.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)},
|
||||
Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
|
||||
}
|
||||
genesis = gspec.MustCommit(db)
|
||||
mux event.TypeMux
|
||||
)
|
||||
|
||||
blockchain, _ := NewBlockChain(db, config, pow.FakePow{}, &mux, vm.Config{})
|
||||
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
|
||||
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, &mux, vm.Config{})
|
||||
blocks, _ := GenerateChain(gspec.Config, genesis, db, 4, func(i int, block *BlockGen) {
|
||||
var (
|
||||
tx *types.Transaction
|
||||
err error
|
||||
@ -1164,7 +1027,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||
}
|
||||
block.AddTx(tx)
|
||||
|
||||
tx, err = basicTx(types.NewEIP155Signer(config.ChainId))
|
||||
tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1176,7 +1039,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||
}
|
||||
block.AddTx(tx)
|
||||
|
||||
tx, err = basicTx(types.NewEIP155Signer(config.ChainId))
|
||||
tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -1204,7 +1067,7 @@ func TestEIP155Transition(t *testing.T) {
|
||||
}
|
||||
|
||||
// generate an invalid chain id transaction
|
||||
config = ¶ms.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
|
||||
config := ¶ms.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
|
||||
blocks, _ = GenerateChain(config, blocks[len(blocks)-1], db, 4, func(i int, block *BlockGen) {
|
||||
var (
|
||||
tx *types.Transaction
|
||||
@ -1236,22 +1099,24 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
||||
address = crypto.PubkeyToAddress(key.PublicKey)
|
||||
funds = big.NewInt(1000000000)
|
||||
theAddr = common.Address{1}
|
||||
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{address, funds})
|
||||
config = ¶ms.ChainConfig{
|
||||
gspec = &Genesis{
|
||||
Config: ¶ms.ChainConfig{
|
||||
ChainId: big.NewInt(1),
|
||||
HomesteadBlock: new(big.Int),
|
||||
EIP155Block: new(big.Int),
|
||||
EIP158Block: big.NewInt(2),
|
||||
},
|
||||
Alloc: GenesisAlloc{address: {Balance: funds}},
|
||||
}
|
||||
genesis = gspec.MustCommit(db)
|
||||
mux event.TypeMux
|
||||
|
||||
blockchain, _ = NewBlockChain(db, config, pow.FakePow{}, &mux, vm.Config{})
|
||||
blockchain, _ = NewBlockChain(db, gspec.Config, pow.FakePow{}, &mux, vm.Config{})
|
||||
)
|
||||
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
|
||||
blocks, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, block *BlockGen) {
|
||||
var (
|
||||
tx *types.Transaction
|
||||
err error
|
||||
signer = types.NewEIP155Signer(config.ChainId)
|
||||
signer = types.NewEIP155Signer(gspec.Config.ChainId)
|
||||
)
|
||||
switch i {
|
||||
case 0:
|
||||
@ -1279,7 +1144,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if blockchain.stateCache.Exist(theAddr) {
|
||||
t.Error("account should not expect")
|
||||
t.Error("account should not exist")
|
||||
}
|
||||
|
||||
// account musn't be created post eip 161
|
||||
@ -1287,6 +1152,6 @@ func TestEIP161AccountRemoval(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if blockchain.stateCache.Exist(theAddr) {
|
||||
t.Error("account should not expect")
|
||||
t.Error("account should not exist")
|
||||
}
|
||||
}
|
||||
|
@ -30,19 +30,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
)
|
||||
|
||||
/*
|
||||
* TODO: move this to another package.
|
||||
*/
|
||||
|
||||
// MakeChainConfig returns a new ChainConfig with the ethereum default chain settings.
|
||||
func MakeChainConfig() *params.ChainConfig {
|
||||
return ¶ms.ChainConfig{
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
DAOForkBlock: nil,
|
||||
DAOForkSupport: true,
|
||||
}
|
||||
}
|
||||
|
||||
// So we can deterministically seed different blockchains
|
||||
var (
|
||||
canonicalSeed = 1
|
||||
@ -154,7 +141,7 @@ func (b *BlockGen) OffsetTime(seconds int64) {
|
||||
if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
|
||||
panic("block time out of range")
|
||||
}
|
||||
b.header.Difficulty = CalcDifficulty(MakeChainConfig(), b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
|
||||
b.header.Difficulty = CalcDifficulty(b.config, b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
|
||||
}
|
||||
|
||||
// GenerateChain creates a chain of n blocks. The first block's
|
||||
@ -170,14 +157,13 @@ func (b *BlockGen) OffsetTime(seconds int64) {
|
||||
// values. Inserting them into BlockChain requires use of FakePow or
|
||||
// a similar non-validating proof of work implementation.
|
||||
func GenerateChain(config *params.ChainConfig, parent *types.Block, db ethdb.Database, n int, gen func(int, *BlockGen)) ([]*types.Block, []types.Receipts) {
|
||||
if config == nil {
|
||||
config = params.TestChainConfig
|
||||
}
|
||||
blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n)
|
||||
genblock := func(i int, h *types.Header, statedb *state.StateDB) (*types.Block, types.Receipts) {
|
||||
b := &BlockGen{parent: parent, i: i, chain: blocks, header: h, statedb: statedb, config: config}
|
||||
|
||||
// Mutate the state and block according to any hard-fork specs
|
||||
if config == nil {
|
||||
config = MakeChainConfig()
|
||||
}
|
||||
if daoBlock := config.DAOForkBlock; daoBlock != nil {
|
||||
limit := new(big.Int).Add(daoBlock, params.DAOForkExtraRange)
|
||||
if h.Number.Cmp(daoBlock) >= 0 && h.Number.Cmp(limit) < 0 {
|
||||
@ -226,7 +212,7 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St
|
||||
Root: state.IntermediateRoot(config.IsEIP158(parent.Number())),
|
||||
ParentHash: parent.Hash(),
|
||||
Coinbase: parent.Coinbase(),
|
||||
Difficulty: CalcDifficulty(MakeChainConfig(), time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
||||
Difficulty: CalcDifficulty(config, time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
||||
GasLimit: CalcGasLimit(parent),
|
||||
GasUsed: new(big.Int),
|
||||
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||
@ -238,14 +224,12 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St
|
||||
// chain. Depending on the full flag, if creates either a full block chain or a
|
||||
// header only chain.
|
||||
func newCanonical(n int, full bool) (ethdb.Database, *BlockChain, error) {
|
||||
// Create the new chain database
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
evmux := &event.TypeMux{}
|
||||
|
||||
// Initialize a fresh chain with only a genesis block
|
||||
genesis, _ := WriteTestNetGenesisBlock(db)
|
||||
gspec := new(Genesis)
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis := gspec.MustCommit(db)
|
||||
|
||||
blockchain, _ := NewBlockChain(db, MakeChainConfig(), pow.FakePow{}, evmux, vm.Config{})
|
||||
blockchain, _ := NewBlockChain(db, params.AllProtocolChanges, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
// Create and inject the requested chain
|
||||
if n == 0 {
|
||||
return db, blockchain, nil
|
||||
|
@ -30,9 +30,6 @@ import (
|
||||
)
|
||||
|
||||
func ExampleGenerateChain() {
|
||||
params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
|
||||
params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
|
||||
|
||||
var (
|
||||
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
|
||||
@ -41,19 +38,20 @@ func ExampleGenerateChain() {
|
||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
|
||||
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
signer = types.HomesteadSigner{}
|
||||
)
|
||||
|
||||
chainConfig := ¶ms.ChainConfig{
|
||||
HomesteadBlock: new(big.Int),
|
||||
}
|
||||
// Ensure that key1 has some funds in the genesis block.
|
||||
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(1000000)})
|
||||
gspec := &Genesis{
|
||||
Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)},
|
||||
Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(1000000)}},
|
||||
}
|
||||
genesis := gspec.MustCommit(db)
|
||||
|
||||
// This call generates a chain of 5 blocks. The function runs for
|
||||
// each block and adds different features to gen based on the
|
||||
// block index.
|
||||
chain, _ := GenerateChain(chainConfig, genesis, db, 5, func(i int, gen *BlockGen) {
|
||||
signer := types.HomesteadSigner{}
|
||||
chain, _ := GenerateChain(gspec.Config, genesis, db, 5, func(i int, gen *BlockGen) {
|
||||
switch i {
|
||||
case 0:
|
||||
// In block 1, addr1 sends addr2 some ether.
|
||||
@ -83,7 +81,7 @@ func ExampleGenerateChain() {
|
||||
|
||||
// Import the chain. This runs all block validation rules.
|
||||
evmux := &event.TypeMux{}
|
||||
blockchain, _ := NewBlockChain(db, chainConfig, pow.FakePow{}, evmux, vm.Config{})
|
||||
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, evmux, vm.Config{})
|
||||
if i, err := blockchain.InsertChain(chain); err != nil {
|
||||
fmt.Printf("insert error (block %d): %v\n", chain[i].NumberU64(), err)
|
||||
return
|
||||
|
@ -67,7 +67,7 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
|
||||
}
|
||||
|
||||
// Move every DAO account and extra-balance account funds into the refund contract
|
||||
for _, addr := range params.DAODrainList {
|
||||
for _, addr := range params.DAODrainList() {
|
||||
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr))
|
||||
statedb.SetBalance(addr, new(big.Int))
|
||||
}
|
||||
|
@ -34,17 +34,18 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||
|
||||
// Generate a common prefix for both pro-forkers and non-forkers
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis := WriteGenesisBlockForTesting(db)
|
||||
gspec := new(Genesis)
|
||||
genesis := gspec.MustCommit(db)
|
||||
prefix, _ := GenerateChain(params.TestChainConfig, genesis, db, int(forkBlock.Int64()-1), func(i int, gen *BlockGen) {})
|
||||
|
||||
// Create the concurrent, conflicting two nodes
|
||||
proDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(proDb)
|
||||
gspec.MustCommit(proDb)
|
||||
proConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: true}
|
||||
proBc, _ := NewBlockChain(proDb, proConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
|
||||
conDb, _ := ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(conDb)
|
||||
gspec.MustCommit(conDb)
|
||||
conConf := ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0), DAOForkBlock: forkBlock, DAOForkSupport: false}
|
||||
conBc, _ := NewBlockChain(conDb, conConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
|
||||
@ -58,7 +59,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||
for i := int64(0); i < params.DAOForkExtraRange.Int64(); i++ {
|
||||
// Create a pro-fork block, and try to feed into the no-fork chain
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(db)
|
||||
gspec.MustCommit(db)
|
||||
bc, _ := NewBlockChain(db, conConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
|
||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
||||
@ -79,7 +80,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||
}
|
||||
// Create a no-fork block, and try to feed into the pro-fork chain
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(db)
|
||||
gspec.MustCommit(db)
|
||||
bc, _ = NewBlockChain(db, proConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
|
||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
||||
@ -101,7 +102,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||
}
|
||||
// Verify that contra-forkers accept pro-fork extra-datas after forking finishes
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(db)
|
||||
gspec.MustCommit(db)
|
||||
bc, _ := NewBlockChain(db, conConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
|
||||
blocks := conBc.GetBlocksFromHash(conBc.CurrentBlock().Hash(), int(conBc.CurrentBlock().NumberU64()+1))
|
||||
@ -117,7 +118,7 @@ func TestDAOForkRangeExtradata(t *testing.T) {
|
||||
}
|
||||
// Verify that pro-forkers accept contra-fork extra-datas after forking finishes
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
WriteGenesisBlockForTesting(db)
|
||||
gspec.MustCommit(db)
|
||||
bc, _ = NewBlockChain(db, proConf, new(pow.FakePow), new(event.TypeMux), vm.Config{})
|
||||
|
||||
blocks = proBc.GetBlocksFromHash(proBc.CurrentBlock().Hash(), int(proBc.CurrentBlock().NumberU64()+1))
|
||||
|
@ -562,7 +562,7 @@ func TestMipmapChain(t *testing.T) {
|
||||
)
|
||||
defer db.Close()
|
||||
|
||||
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{addr, big.NewInt(1000000)})
|
||||
genesis := testGenesis(addr, big.NewInt(1000000)).MustCommit(db)
|
||||
chain, receipts := GenerateChain(params.TestChainConfig, genesis, db, 1010, func(i int, gen *BlockGen) {
|
||||
var receipts types.Receipts
|
||||
switch i {
|
||||
|
File diff suppressed because one or more lines are too long
106
core/gen_genesis.go
Normal file
106
core/gen_genesis.go
Normal file
@ -0,0 +1,106 @@
|
||||
// generated by github.com/fjl/gencodec, do not edit.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func (g *Genesis) MarshalJSON() ([]byte, error) {
|
||||
type GenesisJSON struct {
|
||||
ChainConfig *params.ChainConfig `json:"config" optional:"true"`
|
||||
Nonce *math.HexOrDecimal64 `json:"nonce" optional:"true"`
|
||||
Timestamp *math.HexOrDecimal64 `json:"timestamp" optional:"true"`
|
||||
ParentHash *common.Hash `json:"parentHash" optional:"true"`
|
||||
ExtraData hexutil.Bytes `json:"extraData" optional:"true"`
|
||||
GasLimit *math.HexOrDecimal64 `json:"gasLimit"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||
Mixhash *common.Hash `json:"mixHash" optional:"true"`
|
||||
Coinbase *common.Address `json:"coinbase" optional:"true"`
|
||||
Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc"`
|
||||
}
|
||||
var enc GenesisJSON
|
||||
enc.ChainConfig = g.Config
|
||||
enc.Nonce = (*math.HexOrDecimal64)(&g.Nonce)
|
||||
enc.Timestamp = (*math.HexOrDecimal64)(&g.Timestamp)
|
||||
enc.ParentHash = &g.ParentHash
|
||||
if g.ExtraData != nil {
|
||||
enc.ExtraData = g.ExtraData
|
||||
}
|
||||
enc.GasLimit = (*math.HexOrDecimal64)(&g.GasLimit)
|
||||
enc.Difficulty = (*math.HexOrDecimal256)(g.Difficulty)
|
||||
enc.Mixhash = &g.Mixhash
|
||||
enc.Coinbase = &g.Coinbase
|
||||
if g.Alloc != nil {
|
||||
enc.Alloc = make(map[common.UnprefixedAddress]GenesisAccount, len(g.Alloc))
|
||||
for k, v := range g.Alloc {
|
||||
enc.Alloc[common.UnprefixedAddress(k)] = v
|
||||
}
|
||||
}
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
func (g *Genesis) UnmarshalJSON(input []byte) error {
|
||||
type GenesisJSON struct {
|
||||
ChainConfig *params.ChainConfig `json:"config" optional:"true"`
|
||||
Nonce *math.HexOrDecimal64 `json:"nonce" optional:"true"`
|
||||
Timestamp *math.HexOrDecimal64 `json:"timestamp" optional:"true"`
|
||||
ParentHash *common.Hash `json:"parentHash" optional:"true"`
|
||||
ExtraData hexutil.Bytes `json:"extraData" optional:"true"`
|
||||
GasLimit *math.HexOrDecimal64 `json:"gasLimit"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||
Mixhash *common.Hash `json:"mixHash" optional:"true"`
|
||||
Coinbase *common.Address `json:"coinbase" optional:"true"`
|
||||
Alloc map[common.UnprefixedAddress]GenesisAccount `json:"alloc"`
|
||||
}
|
||||
var dec GenesisJSON
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
var x Genesis
|
||||
if dec.ChainConfig != nil {
|
||||
x.Config = dec.ChainConfig
|
||||
}
|
||||
if dec.Nonce != nil {
|
||||
x.Nonce = uint64(*dec.Nonce)
|
||||
}
|
||||
if dec.Timestamp != nil {
|
||||
x.Timestamp = uint64(*dec.Timestamp)
|
||||
}
|
||||
if dec.ParentHash != nil {
|
||||
x.ParentHash = *dec.ParentHash
|
||||
}
|
||||
if dec.ExtraData != nil {
|
||||
x.ExtraData = dec.ExtraData
|
||||
}
|
||||
if dec.GasLimit == nil {
|
||||
return errors.New("missing required field 'gasLimit' for Genesis")
|
||||
}
|
||||
x.GasLimit = uint64(*dec.GasLimit)
|
||||
if dec.Difficulty == nil {
|
||||
return errors.New("missing required field 'difficulty' for Genesis")
|
||||
}
|
||||
x.Difficulty = (*big.Int)(dec.Difficulty)
|
||||
if dec.Mixhash != nil {
|
||||
x.Mixhash = *dec.Mixhash
|
||||
}
|
||||
if dec.Coinbase != nil {
|
||||
x.Coinbase = *dec.Coinbase
|
||||
}
|
||||
if dec.Alloc == nil {
|
||||
return errors.New("missing required field 'alloc' for Genesis")
|
||||
}
|
||||
x.Alloc = make(GenesisAlloc, len(dec.Alloc))
|
||||
for k, v := range dec.Alloc {
|
||||
x.Alloc[common.Address(k)] = v
|
||||
}
|
||||
*g = x
|
||||
return nil
|
||||
}
|
61
core/gen_genesis_account.go
Normal file
61
core/gen_genesis_account.go
Normal file
@ -0,0 +1,61 @@
|
||||
// generated by github.com/fjl/gencodec, do not edit.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
)
|
||||
|
||||
func (g *GenesisAccount) MarshalJSON() ([]byte, error) {
|
||||
type GenesisAccountJSON struct {
|
||||
Code hexutil.Bytes `json:"code" optional:"true"`
|
||||
Storage map[common.Hash]common.Hash `json:"storage" optional:"true"`
|
||||
Balance *math.HexOrDecimal256 `json:"balance"`
|
||||
Nonce *math.HexOrDecimal64 `json:"nonce" optional:"true"`
|
||||
}
|
||||
var enc GenesisAccountJSON
|
||||
if g.Code != nil {
|
||||
enc.Code = g.Code
|
||||
}
|
||||
if g.Storage != nil {
|
||||
enc.Storage = g.Storage
|
||||
}
|
||||
enc.Balance = (*math.HexOrDecimal256)(g.Balance)
|
||||
enc.Nonce = (*math.HexOrDecimal64)(&g.Nonce)
|
||||
return json.Marshal(&enc)
|
||||
}
|
||||
|
||||
func (g *GenesisAccount) UnmarshalJSON(input []byte) error {
|
||||
type GenesisAccountJSON struct {
|
||||
Code hexutil.Bytes `json:"code" optional:"true"`
|
||||
Storage map[common.Hash]common.Hash `json:"storage" optional:"true"`
|
||||
Balance *math.HexOrDecimal256 `json:"balance"`
|
||||
Nonce *math.HexOrDecimal64 `json:"nonce" optional:"true"`
|
||||
}
|
||||
var dec GenesisAccountJSON
|
||||
if err := json.Unmarshal(input, &dec); err != nil {
|
||||
return err
|
||||
}
|
||||
var x GenesisAccount
|
||||
if dec.Code != nil {
|
||||
x.Code = dec.Code
|
||||
}
|
||||
if dec.Storage != nil {
|
||||
x.Storage = dec.Storage
|
||||
}
|
||||
if dec.Balance == nil {
|
||||
return errors.New("missing required field 'balance' for GenesisAccount")
|
||||
}
|
||||
x.Balance = (*big.Int)(dec.Balance)
|
||||
if dec.Nonce != nil {
|
||||
x.Nonce = uint64(*dec.Nonce)
|
||||
}
|
||||
*g = x
|
||||
return nil
|
||||
}
|
386
core/genesis.go
386
core/genesis.go
@ -17,230 +17,286 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"compress/bzip2"
|
||||
"compress/gzip"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
// WriteGenesisBlock writes the genesis block to the database as block number 0
|
||||
func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, error) {
|
||||
contents, err := ioutil.ReadAll(reader)
|
||||
//go:generate gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
|
||||
//go:generate gencodec -type GenesisAccount -field-override genesisAccountMarshaling -out gen_genesis_account.go
|
||||
|
||||
var errGenesisNoConfig = errors.New("genesis has no chain configuration")
|
||||
|
||||
// Genesis specifies the header fields, state of a genesis block. It also defines hard
|
||||
// fork switch-over blocks through the chain configuration.
|
||||
type Genesis struct {
|
||||
Config *params.ChainConfig `json:"config" optional:"true"`
|
||||
Nonce uint64 `json:"nonce" optional:"true"`
|
||||
Timestamp uint64 `json:"timestamp" optional:"true"`
|
||||
ParentHash common.Hash `json:"parentHash" optional:"true"`
|
||||
ExtraData []byte `json:"extraData" optional:"true"`
|
||||
GasLimit uint64 `json:"gasLimit"`
|
||||
Difficulty *big.Int `json:"difficulty"`
|
||||
Mixhash common.Hash `json:"mixHash" optional:"true"`
|
||||
Coinbase common.Address `json:"coinbase" optional:"true"`
|
||||
Alloc GenesisAlloc `json:"alloc"`
|
||||
}
|
||||
|
||||
// GenesisAlloc specifies the initial state that is part of the genesis block.
|
||||
type GenesisAlloc map[common.Address]GenesisAccount
|
||||
|
||||
// GenesisAccount is an account in the state of the genesis block.
|
||||
type GenesisAccount struct {
|
||||
Code []byte `json:"code" optional:"true"`
|
||||
Storage map[common.Hash]common.Hash `json:"storage" optional:"true"`
|
||||
Balance *big.Int `json:"balance"`
|
||||
Nonce uint64 `json:"nonce" optional:"true"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
type genesisSpecMarshaling struct {
|
||||
Nonce math.HexOrDecimal64
|
||||
Timestamp math.HexOrDecimal64
|
||||
ExtraData hexutil.Bytes
|
||||
GasLimit math.HexOrDecimal64
|
||||
Difficulty *math.HexOrDecimal256
|
||||
Alloc map[common.UnprefixedAddress]GenesisAccount
|
||||
}
|
||||
type genesisAccountMarshaling struct {
|
||||
Code hexutil.Bytes
|
||||
Balance *math.HexOrDecimal256
|
||||
Nonce math.HexOrDecimal64
|
||||
}
|
||||
|
||||
// GenesisMismatchError is raised when trying to overwrite an existing
|
||||
// genesis block with an incompatible one.
|
||||
type GenesisMismatchError struct {
|
||||
Stored, New common.Hash
|
||||
}
|
||||
|
||||
func (e *GenesisMismatchError) Error() string {
|
||||
return fmt.Sprintf("wrong genesis block in database (have %x, new %x)", e.Stored[:8], e.New[:8])
|
||||
}
|
||||
|
||||
// SetupGenesisBlock writes or updates the genesis block in db.
|
||||
// The block that will be used is:
|
||||
//
|
||||
// genesis == nil genesis != nil
|
||||
// +------------------------------------------
|
||||
// db has no genesis | main-net default | genesis
|
||||
// db has genesis | from DB | genesis (if compatible)
|
||||
//
|
||||
// The stored chain configuration will be updated if it is compatible (i.e. does not
|
||||
// specify a fork block below the local head block). In case of a conflict, the
|
||||
// error is a *params.ConfigCompatError and the new, unwritten config is returned.
|
||||
//
|
||||
// The returned chain configuration is never nil.
|
||||
func SetupGenesisBlock(db ethdb.Database, genesis *Genesis) (*params.ChainConfig, common.Hash, error) {
|
||||
if genesis != nil && genesis.Config == nil {
|
||||
return params.AllProtocolChanges, common.Hash{}, errGenesisNoConfig
|
||||
}
|
||||
|
||||
// Just commit the new block if there is no stored genesis block.
|
||||
stored := GetCanonicalHash(db, 0)
|
||||
if (stored == common.Hash{}) {
|
||||
if genesis == nil {
|
||||
log.Info("Writing default main-net genesis block")
|
||||
genesis = DefaultGenesisBlock()
|
||||
} else {
|
||||
log.Info("Writing custom genesis block")
|
||||
}
|
||||
block, err := genesis.Commit(db)
|
||||
return genesis.Config, block.Hash(), err
|
||||
}
|
||||
|
||||
// Check whether the genesis block is already written.
|
||||
if genesis != nil {
|
||||
block, _ := genesis.ToBlock()
|
||||
hash := block.Hash()
|
||||
if hash != stored {
|
||||
return genesis.Config, block.Hash(), &GenesisMismatchError{stored, hash}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the existing chain configuration.
|
||||
newcfg := genesis.configOrDefault(stored)
|
||||
storedcfg, err := GetChainConfig(db, stored)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if err == ChainConfigNotFoundErr {
|
||||
// This case happens if a genesis write was interrupted.
|
||||
log.Warn("Found genesis block without chain config")
|
||||
err = WriteChainConfig(db, stored, newcfg)
|
||||
}
|
||||
return newcfg, stored, err
|
||||
}
|
||||
// Special case: don't change the existing config of a non-mainnet chain if no new
|
||||
// config is supplied. These chains would get AllProtocolChanges (and a compat error)
|
||||
// if we just continued here.
|
||||
if genesis == nil && stored != params.MainNetGenesisHash {
|
||||
return storedcfg, stored, nil
|
||||
}
|
||||
|
||||
var genesis struct {
|
||||
ChainConfig *params.ChainConfig `json:"config"`
|
||||
Nonce string
|
||||
Timestamp string
|
||||
ParentHash string
|
||||
ExtraData string
|
||||
GasLimit string
|
||||
Difficulty string
|
||||
Mixhash string
|
||||
Coinbase string
|
||||
Alloc map[string]struct {
|
||||
Code string
|
||||
Storage map[string]string
|
||||
Balance string
|
||||
Nonce string
|
||||
// Check config compatibility and write the config. Compatibility errors
|
||||
// are returned to the caller unless we're already at block zero.
|
||||
height := GetBlockNumber(db, GetHeadHeaderHash(db))
|
||||
if height == missingNumber {
|
||||
return newcfg, stored, fmt.Errorf("missing block number for head header hash")
|
||||
}
|
||||
compatErr := storedcfg.CheckCompatible(newcfg, height)
|
||||
if compatErr != nil && height != 0 && compatErr.RewindTo != 0 {
|
||||
return newcfg, stored, compatErr
|
||||
}
|
||||
return newcfg, stored, WriteChainConfig(db, stored, newcfg)
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(contents, &genesis); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if genesis.ChainConfig == nil {
|
||||
genesis.ChainConfig = params.AllProtocolChanges
|
||||
func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
||||
switch {
|
||||
case g != nil:
|
||||
return g.Config
|
||||
case ghash == params.MainNetGenesisHash:
|
||||
return params.MainnetChainConfig
|
||||
case ghash == params.TestNetGenesisHash:
|
||||
return params.TestnetChainConfig
|
||||
default:
|
||||
return params.AllProtocolChanges
|
||||
}
|
||||
}
|
||||
|
||||
// creating with empty hash always works
|
||||
statedb, _ := state.New(common.Hash{}, chainDb)
|
||||
for addr, account := range genesis.Alloc {
|
||||
balance, ok := math.ParseBig256(account.Balance)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid balance for account %s: %q", addr, account.Balance)
|
||||
}
|
||||
nonce, ok := math.ParseUint64(account.Nonce)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid nonce for account %s: %q", addr, account.Nonce)
|
||||
}
|
||||
|
||||
address := common.HexToAddress(addr)
|
||||
statedb.AddBalance(address, balance)
|
||||
statedb.SetCode(address, common.FromHex(account.Code))
|
||||
statedb.SetNonce(address, nonce)
|
||||
// ToBlock creates the block and state of a genesis specification.
|
||||
func (g *Genesis) ToBlock() (*types.Block, *state.StateDB) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
for addr, account := range g.Alloc {
|
||||
statedb.AddBalance(addr, account.Balance)
|
||||
statedb.SetCode(addr, account.Code)
|
||||
statedb.SetNonce(addr, account.Nonce)
|
||||
for key, value := range account.Storage {
|
||||
statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
|
||||
statedb.SetState(addr, key, value)
|
||||
}
|
||||
}
|
||||
root, stateBatch := statedb.CommitBatch(false)
|
||||
|
||||
difficulty, ok := math.ParseBig256(genesis.Difficulty)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid difficulty: %q", genesis.Difficulty)
|
||||
}
|
||||
gaslimit, ok := math.ParseUint64(genesis.GasLimit)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid gas limit: %q", genesis.GasLimit)
|
||||
}
|
||||
nonce, ok := math.ParseUint64(genesis.Nonce)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid nonce: %q", genesis.Nonce)
|
||||
}
|
||||
timestamp, ok := math.ParseBig256(genesis.Timestamp)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid timestamp: %q", genesis.Timestamp)
|
||||
}
|
||||
|
||||
block := types.NewBlock(&types.Header{
|
||||
Nonce: types.EncodeNonce(nonce),
|
||||
Time: timestamp,
|
||||
ParentHash: common.HexToHash(genesis.ParentHash),
|
||||
Extra: common.FromHex(genesis.ExtraData),
|
||||
GasLimit: new(big.Int).SetUint64(gaslimit),
|
||||
Difficulty: difficulty,
|
||||
MixDigest: common.HexToHash(genesis.Mixhash),
|
||||
Coinbase: common.HexToAddress(genesis.Coinbase),
|
||||
root := statedb.IntermediateRoot(false)
|
||||
head := &types.Header{
|
||||
Nonce: types.EncodeNonce(g.Nonce),
|
||||
Time: new(big.Int).SetUint64(g.Timestamp),
|
||||
ParentHash: g.ParentHash,
|
||||
Extra: g.ExtraData,
|
||||
GasLimit: new(big.Int).SetUint64(g.GasLimit),
|
||||
Difficulty: g.Difficulty,
|
||||
MixDigest: g.Mixhash,
|
||||
Coinbase: g.Coinbase,
|
||||
Root: root,
|
||||
}, nil, nil, nil)
|
||||
|
||||
if block := GetBlock(chainDb, block.Hash(), block.NumberU64()); block != nil {
|
||||
log.Info("Genesis block known, writing canonical number")
|
||||
err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return block, nil
|
||||
if g.GasLimit == 0 {
|
||||
head.GasLimit = params.GenesisGasLimit
|
||||
}
|
||||
if g.Difficulty == nil {
|
||||
head.Difficulty = params.GenesisDifficulty
|
||||
}
|
||||
return types.NewBlock(head, nil, nil, nil), statedb
|
||||
}
|
||||
|
||||
if err := stateBatch.Write(); err != nil {
|
||||
// Commit writes the block and state of a genesis specification to the database.
|
||||
// The block is committed as the canonical head block.
|
||||
func (g *Genesis) Commit(db ethdb.Database) (*types.Block, error) {
|
||||
block, statedb := g.ToBlock()
|
||||
if _, err := statedb.CommitTo(db, false); err != nil {
|
||||
return nil, fmt.Errorf("cannot write state: %v", err)
|
||||
}
|
||||
if err := WriteTd(chainDb, block.Hash(), block.NumberU64(), difficulty); err != nil {
|
||||
if err := WriteTd(db, block.Hash(), block.NumberU64(), g.Difficulty); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := WriteBlock(chainDb, block); err != nil {
|
||||
if err := WriteBlock(db, block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := WriteBlockReceipts(chainDb, block.Hash(), block.NumberU64(), nil); err != nil {
|
||||
if err := WriteBlockReceipts(db, block.Hash(), block.NumberU64(), nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := WriteCanonicalHash(chainDb, block.Hash(), block.NumberU64()); err != nil {
|
||||
if err := WriteCanonicalHash(db, block.Hash(), block.NumberU64()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := WriteHeadBlockHash(chainDb, block.Hash()); err != nil {
|
||||
if err := WriteHeadBlockHash(db, block.Hash()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := WriteChainConfig(chainDb, block.Hash(), genesis.ChainConfig); err != nil {
|
||||
if err := WriteHeadHeaderHash(db, block.Hash()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return block, nil
|
||||
config := g.Config
|
||||
if config == nil {
|
||||
config = params.AllProtocolChanges
|
||||
}
|
||||
return block, WriteChainConfig(db, block.Hash(), config)
|
||||
}
|
||||
|
||||
// GenesisBlockForTesting creates a block in which addr has the given wei balance.
|
||||
// The state trie of the block is written to db. the passed db needs to contain a state root
|
||||
func GenesisBlockForTesting(db ethdb.Database, addr common.Address, balance *big.Int) *types.Block {
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
obj := statedb.GetOrNewStateObject(addr)
|
||||
obj.SetBalance(balance)
|
||||
root, err := statedb.Commit(false)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot write state: %v", err))
|
||||
}
|
||||
block := types.NewBlock(&types.Header{
|
||||
Difficulty: params.GenesisDifficulty,
|
||||
GasLimit: params.GenesisGasLimit,
|
||||
Root: root,
|
||||
}, nil, nil, nil)
|
||||
return block
|
||||
}
|
||||
|
||||
type GenesisAccount struct {
|
||||
Address common.Address
|
||||
Balance *big.Int
|
||||
}
|
||||
|
||||
func WriteGenesisBlockForTesting(db ethdb.Database, accounts ...GenesisAccount) *types.Block {
|
||||
accountJson := "{"
|
||||
for i, account := range accounts {
|
||||
if i != 0 {
|
||||
accountJson += ","
|
||||
}
|
||||
accountJson += fmt.Sprintf(`"0x%x":{"balance":"%d"}`, account.Address, account.Balance)
|
||||
}
|
||||
accountJson += "}"
|
||||
|
||||
testGenesis := fmt.Sprintf(`{
|
||||
"nonce":"0x%x",
|
||||
"gasLimit":"0x%x",
|
||||
"difficulty":"0x%x",
|
||||
"alloc": %s
|
||||
}`, types.EncodeNonce(0), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes(), accountJson)
|
||||
block, err := WriteGenesisBlock(db, strings.NewReader(testGenesis))
|
||||
// MustCommit writes the genesis block and state to db, panicking on error.
|
||||
// The block is committed as the canonical head block.
|
||||
func (g *Genesis) MustCommit(db ethdb.Database) *types.Block {
|
||||
block, err := g.Commit(db)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
||||
// WriteDefaultGenesisBlock assembles the official Ethereum genesis block and
|
||||
// writes it - along with all associated state - into a chain database.
|
||||
func WriteDefaultGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
|
||||
return WriteGenesisBlock(chainDb, strings.NewReader(DefaultGenesisBlock()))
|
||||
// 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}}}
|
||||
return g.MustCommit(db)
|
||||
}
|
||||
|
||||
// WriteTestNetGenesisBlock assembles the test network genesis block and
|
||||
// writes it - along with all associated state - into a chain database.
|
||||
func WriteTestNetGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
|
||||
return WriteGenesisBlock(chainDb, strings.NewReader(DefaultTestnetGenesisBlock()))
|
||||
// DefaultGenesisBlock returns the Ethereum main net genesis block.
|
||||
func DefaultGenesisBlock() *Genesis {
|
||||
return &Genesis{
|
||||
Config: params.MainnetChainConfig,
|
||||
Nonce: 66,
|
||||
ExtraData: hexutil.MustDecode("0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"),
|
||||
GasLimit: 5000,
|
||||
Difficulty: big.NewInt(17179869184),
|
||||
Alloc: decodePrealloc(mainnetAllocData),
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultGenesisBlock assembles a JSON string representing the default Ethereum
|
||||
// genesis block.
|
||||
func DefaultGenesisBlock() string {
|
||||
reader, err := gzip.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultGenesisBlock)))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to access default genesis: %v", err))
|
||||
// DefaultTestnetGenesisBlock returns the Ropsten network genesis block.
|
||||
func DefaultTestnetGenesisBlock() *Genesis {
|
||||
return &Genesis{
|
||||
Config: params.TestnetChainConfig,
|
||||
Nonce: 66,
|
||||
ExtraData: hexutil.MustDecode("0x3535353535353535353535353535353535353535353535353535353535353535"),
|
||||
GasLimit: 16777216,
|
||||
Difficulty: big.NewInt(1048576),
|
||||
Alloc: decodePrealloc(testnetAllocData),
|
||||
}
|
||||
blob, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to load default genesis: %v", err))
|
||||
}
|
||||
return string(blob)
|
||||
}
|
||||
|
||||
// DefaultTestnetGenesisBlock assembles a JSON string representing the default Ethereum
|
||||
// test network genesis block.
|
||||
func DefaultTestnetGenesisBlock() string {
|
||||
reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultTestnetGenesisBlock)))
|
||||
blob, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to load default genesis: %v", err))
|
||||
// DevGenesisBlock returns the 'geth --dev' genesis block.
|
||||
func DevGenesisBlock() *Genesis {
|
||||
return &Genesis{
|
||||
Config: params.AllProtocolChanges,
|
||||
Nonce: 42,
|
||||
GasLimit: 4712388,
|
||||
Difficulty: big.NewInt(131072),
|
||||
Alloc: decodePrealloc(devAllocData),
|
||||
}
|
||||
return string(blob)
|
||||
}
|
||||
|
||||
// DevGenesisBlock assembles a JSON string representing a local dev genesis block.
|
||||
func DevGenesisBlock() string {
|
||||
reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultDevnetGenesisBlock)))
|
||||
blob, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to load dev genesis: %v", err))
|
||||
func decodePrealloc(data string) GenesisAlloc {
|
||||
var p []struct{ Addr, Balance *big.Int }
|
||||
if err := rlp.NewStream(strings.NewReader(data), 0).Decode(&p); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(blob)
|
||||
ga := make(GenesisAlloc, len(p))
|
||||
for _, account := range p {
|
||||
ga[common.BigToAddress(account.Addr)] = GenesisAccount{Balance: account.Balance}
|
||||
}
|
||||
return ga
|
||||
}
|
||||
|
25
core/genesis_alloc.go
Normal file
25
core/genesis_alloc.go
Normal file
File diff suppressed because one or more lines are too long
161
core/genesis_test.go
Normal file
161
core/genesis_test.go
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2017 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 core
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
)
|
||||
|
||||
func TestDefaultGenesisBlock(t *testing.T) {
|
||||
block, _ := DefaultGenesisBlock().ToBlock()
|
||||
if block.Hash() != params.MainNetGenesisHash {
|
||||
t.Errorf("wrong mainnet genesis hash, got %v, want %v", block.Hash(), params.MainNetGenesisHash)
|
||||
}
|
||||
block, _ = DefaultTestnetGenesisBlock().ToBlock()
|
||||
if block.Hash() != params.TestNetGenesisHash {
|
||||
t.Errorf("wrong testnet genesis hash, got %v, want %v", block.Hash(), params.TestNetGenesisHash)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupGenesis(t *testing.T) {
|
||||
var (
|
||||
customghash = common.HexToHash("0x89c99d90b79719238d2645c7642f2c9295246e80775b38cfd162b696817fbd50")
|
||||
customg = Genesis{
|
||||
Config: ¶ms.ChainConfig{HomesteadBlock: big.NewInt(3)},
|
||||
Alloc: GenesisAlloc{
|
||||
{1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}},
|
||||
},
|
||||
}
|
||||
oldcustomg = customg
|
||||
)
|
||||
oldcustomg.Config = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(2)}
|
||||
tests := []struct {
|
||||
name string
|
||||
fn func(ethdb.Database) (*params.ChainConfig, common.Hash, error)
|
||||
wantConfig *params.ChainConfig
|
||||
wantHash common.Hash
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "genesis without ChainConfig",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
return SetupGenesisBlock(db, new(Genesis))
|
||||
},
|
||||
wantErr: errGenesisNoConfig,
|
||||
wantConfig: params.AllProtocolChanges,
|
||||
},
|
||||
{
|
||||
name: "no block in DB, genesis == nil",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
return SetupGenesisBlock(db, nil)
|
||||
},
|
||||
wantHash: params.MainNetGenesisHash,
|
||||
wantConfig: params.MainnetChainConfig,
|
||||
},
|
||||
{
|
||||
name: "mainnet block in DB, genesis == nil",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
DefaultGenesisBlock().MustCommit(db)
|
||||
return SetupGenesisBlock(db, nil)
|
||||
},
|
||||
wantHash: params.MainNetGenesisHash,
|
||||
wantConfig: params.MainnetChainConfig,
|
||||
},
|
||||
{
|
||||
name: "custom block in DB, genesis == nil",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
customg.MustCommit(db)
|
||||
return SetupGenesisBlock(db, nil)
|
||||
},
|
||||
wantHash: customghash,
|
||||
wantConfig: customg.Config,
|
||||
},
|
||||
{
|
||||
name: "custom block in DB, genesis == testnet",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
customg.MustCommit(db)
|
||||
return SetupGenesisBlock(db, DefaultTestnetGenesisBlock())
|
||||
},
|
||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.TestNetGenesisHash},
|
||||
wantHash: params.TestNetGenesisHash,
|
||||
wantConfig: params.TestnetChainConfig,
|
||||
},
|
||||
{
|
||||
name: "compatible config in DB",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
oldcustomg.MustCommit(db)
|
||||
return SetupGenesisBlock(db, &customg)
|
||||
},
|
||||
wantHash: customghash,
|
||||
wantConfig: customg.Config,
|
||||
},
|
||||
{
|
||||
name: "incompatible config in DB",
|
||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, error) {
|
||||
// Commit the 'old' genesis block with Homestead transition at #2.
|
||||
// Advance to block #4, past the homestead transition block of customg.
|
||||
genesis := oldcustomg.MustCommit(db)
|
||||
bc, _ := NewBlockChain(db, oldcustomg.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
bc.SetValidator(bproc{})
|
||||
bc.InsertChain(makeBlockChainWithDiff(genesis, []int{2, 3, 4, 5}, 0))
|
||||
bc.CurrentBlock()
|
||||
// This should return a compatibility error.
|
||||
return SetupGenesisBlock(db, &customg)
|
||||
},
|
||||
wantHash: customghash,
|
||||
wantConfig: customg.Config,
|
||||
wantErr: ¶ms.ConfigCompatError{
|
||||
What: "Homestead fork block",
|
||||
StoredConfig: big.NewInt(2),
|
||||
NewConfig: big.NewInt(3),
|
||||
RewindTo: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
config, hash, err := test.fn(db)
|
||||
// Check the return values.
|
||||
if !reflect.DeepEqual(err, test.wantErr) {
|
||||
spew := spew.ConfigState{DisablePointerAddresses: true, DisableCapacities: true}
|
||||
t.Errorf("%s: returned error %#v, want %#v", test.name, spew.NewFormatter(err), spew.NewFormatter(test.wantErr))
|
||||
}
|
||||
if !reflect.DeepEqual(config, test.wantConfig) {
|
||||
t.Errorf("%s:\nreturned %v\nwant %v", test.name, config, test.wantConfig)
|
||||
}
|
||||
if hash != test.wantHash {
|
||||
t.Errorf("%s: returned hash %s, want %s", test.name, hash.Hex(), test.wantHash.Hex())
|
||||
} else if err == nil {
|
||||
// Check database content.
|
||||
stored := GetBlock(db, test.wantHash, 0)
|
||||
if stored.Hash() != test.wantHash {
|
||||
t.Errorf("%s: block in DB has hash %s, want %s", test.name, stored.Hash(), test.wantHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -97,12 +97,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, getValid
|
||||
|
||||
hc.genesisHeader = hc.GetHeaderByNumber(0)
|
||||
if hc.genesisHeader == nil {
|
||||
genesisBlock, err := WriteDefaultGenesisBlock(chainDb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Warn("Wrote default Ethereum genesis block")
|
||||
hc.genesisHeader = genesisBlock.Header()
|
||||
return nil, ErrNoGenesis
|
||||
}
|
||||
|
||||
hc.currentHeader = hc.genesisHeader
|
||||
|
85
core/mkalloc.go
Normal file
85
core/mkalloc.go
Normal file
@ -0,0 +1,85 @@
|
||||
// Copyright 2017 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/>.
|
||||
|
||||
// +build none
|
||||
|
||||
/*
|
||||
|
||||
The mkalloc tool creates the genesis allocation constants in genesis_alloc.go
|
||||
It outputs a const declaration that contains an RLP-encoded list of (address, balance) tuples.
|
||||
|
||||
go run mkalloc.go genesis.json
|
||||
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
type allocItem struct{ Addr, Balance *big.Int }
|
||||
|
||||
type allocList []allocItem
|
||||
|
||||
func (a allocList) Len() int { return len(a) }
|
||||
func (a allocList) Less(i, j int) bool { return a[i].Addr.Cmp(a[j].Addr) < 0 }
|
||||
func (a allocList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
func makelist(g *core.Genesis) allocList {
|
||||
a := make(allocList, 0, len(g.Alloc))
|
||||
for addr, account := range g.Alloc {
|
||||
if len(account.Storage) > 0 || len(account.Code) > 0 || account.Nonce != 0 {
|
||||
panic(fmt.Sprintf("can't encode account %x", addr))
|
||||
}
|
||||
a = append(a, allocItem{addr.Big(), account.Balance})
|
||||
}
|
||||
sort.Sort(a)
|
||||
return a
|
||||
}
|
||||
|
||||
func makealloc(g *core.Genesis) string {
|
||||
a := makelist(g)
|
||||
data, err := rlp.EncodeToBytes(a)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return strconv.QuoteToASCII(string(data))
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintln(os.Stderr, "Usage: mkalloc genesis.json")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
g := new(core.Genesis)
|
||||
file, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := json.NewDecoder(file).Decode(g); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("const allocData =", makealloc(g))
|
||||
}
|
@ -611,7 +611,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error)
|
||||
// the root hash stored in a block.
|
||||
func (s *StateDB) CommitBatch(deleteEmptyObjects bool) (root common.Hash, batch ethdb.Batch) {
|
||||
batch = s.db.NewBatch()
|
||||
root, _ = s.commit(batch, deleteEmptyObjects)
|
||||
root, _ = s.CommitTo(batch, deleteEmptyObjects)
|
||||
|
||||
log.Debug("Trie cache stats after commit", "misses", trie.CacheMisses(), "unloads", trie.CacheUnloads())
|
||||
return root, batch
|
||||
@ -623,7 +623,8 @@ func (s *StateDB) clearJournalAndRefund() {
|
||||
s.refund = new(big.Int)
|
||||
}
|
||||
|
||||
func (s *StateDB) commit(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (root common.Hash, err error) {
|
||||
// CommitTo writes the state to the given database.
|
||||
func (s *StateDB) CommitTo(dbw trie.DatabaseWriter, deleteEmptyObjects bool) (root common.Hash, err error) {
|
||||
defer s.clearJournalAndRefund()
|
||||
|
||||
// Commit objects to the trie.
|
||||
|
@ -42,7 +42,7 @@ func setupTxPool() (*TxPool, *ecdsa.PrivateKey) {
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
|
||||
key, _ := crypto.GenerateKey()
|
||||
newPool := NewTxPool(testChainConfig(), new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
newPool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
newPool.resetState()
|
||||
|
||||
return newPool, key
|
||||
@ -91,7 +91,7 @@ func TestStateChangeDuringPoolReset(t *testing.T) {
|
||||
|
||||
gasLimitFunc := func() *big.Int { return big.NewInt(1000000000) }
|
||||
|
||||
txpool := NewTxPool(testChainConfig(), mux, stateFunc, gasLimitFunc)
|
||||
txpool := NewTxPool(params.TestChainConfig, mux, stateFunc, gasLimitFunc)
|
||||
txpool.resetState()
|
||||
|
||||
nonce := txpool.State().GetNonce(address)
|
||||
@ -564,7 +564,7 @@ func TestTransactionQueueGlobalLimiting(t *testing.T) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
|
||||
pool := NewTxPool(testChainConfig(), new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
pool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
pool.resetState()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
@ -713,7 +713,7 @@ func TestTransactionPendingGlobalLimiting(t *testing.T) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
|
||||
pool := NewTxPool(testChainConfig(), new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
pool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
pool.resetState()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
@ -759,7 +759,7 @@ func TestTransactionPendingMinimumAllowance(t *testing.T) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb, _ := state.New(common.Hash{}, db)
|
||||
|
||||
pool := NewTxPool(testChainConfig(), new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
pool := NewTxPool(params.TestChainConfig, new(event.TypeMux), func() (*state.StateDB, error) { return statedb, nil }, func() *big.Int { return big.NewInt(1000000) })
|
||||
pool.resetState()
|
||||
|
||||
// Create a number of test accounts and fund them
|
||||
|
@ -27,7 +27,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
@ -119,19 +118,6 @@ func newTransaction(nonce uint64, to *common.Address, amount, gasLimit, gasPrice
|
||||
return &Transaction{data: d}
|
||||
}
|
||||
|
||||
func pickSigner(rules params.Rules) Signer {
|
||||
var signer Signer
|
||||
switch {
|
||||
case rules.IsEIP155:
|
||||
signer = NewEIP155Signer(rules.ChainId)
|
||||
case rules.IsHomestead:
|
||||
signer = HomesteadSigner{}
|
||||
default:
|
||||
signer = FrontierSigner{}
|
||||
}
|
||||
return signer
|
||||
}
|
||||
|
||||
// ChainId returns which chain id this transaction was signed for (if at all)
|
||||
func (tx *Transaction) ChainId() *big.Int {
|
||||
return deriveChainId(tx.data.V)
|
||||
|
@ -112,6 +112,9 @@ type EIP155Signer struct {
|
||||
}
|
||||
|
||||
func NewEIP155Signer(chainId *big.Int) EIP155Signer {
|
||||
if chainId == nil {
|
||||
chainId = new(big.Int)
|
||||
}
|
||||
return EIP155Signer{
|
||||
chainId: chainId,
|
||||
chainIdMul: new(big.Int).Mul(chainId, big.NewInt(2)),
|
||||
|
@ -18,11 +18,9 @@
|
||||
package eth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -60,10 +58,12 @@ var (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ChainConfig *params.ChainConfig // chain configuration
|
||||
// The genesis block, which is inserted if the database is empty.
|
||||
// If nil, the Ethereum main net block is used.
|
||||
Genesis *core.Genesis
|
||||
|
||||
NetworkId int // Network ID to use for selecting peers to connect to
|
||||
Genesis string // Genesis JSON to seed the chain database with
|
||||
|
||||
FastSync bool // Enables the state download based fast synchronisation algorithm
|
||||
LightMode bool // Running in light client mode
|
||||
LightServ int // Maximum percentage of time allowed for serving LES requests
|
||||
@ -100,9 +100,6 @@ type Config struct {
|
||||
GpobaseCorrectionFactor int
|
||||
|
||||
EnablePreimageRecording bool
|
||||
|
||||
TestGenesisBlock *types.Block // Genesis block to seed the chain database with (testing only!)
|
||||
TestGenesisState ethdb.Database // Genesis state to seed the database with (testing only!)
|
||||
}
|
||||
|
||||
type LesServer interface {
|
||||
@ -155,11 +152,15 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||
return nil, err
|
||||
}
|
||||
stopDbUpgrade := upgradeSequentialKeys(chainDb)
|
||||
if err := SetupGenesisBlock(&chainDb, config); err != nil {
|
||||
return nil, err
|
||||
chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis)
|
||||
if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok {
|
||||
return nil, genesisErr
|
||||
}
|
||||
log.Info("Initialised chain configuration", "config", chainConfig)
|
||||
|
||||
eth := &Ethereum{
|
||||
chainDb: chainDb,
|
||||
chainConfig: chainConfig,
|
||||
eventMux: ctx.EventMux,
|
||||
accountManager: ctx.AccountManager,
|
||||
pow: CreatePoW(ctx, config),
|
||||
@ -184,33 +185,18 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||
core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
|
||||
}
|
||||
|
||||
// load the genesis block or write a new one if no genesis
|
||||
// block is prenent in the database.
|
||||
genesis := core.GetBlock(chainDb, core.GetCanonicalHash(chainDb, 0), 0)
|
||||
if genesis == nil {
|
||||
genesis, err = core.WriteDefaultGenesisBlock(chainDb)
|
||||
vmConfig := vm.Config{EnablePreimageRecording: config.EnablePreimageRecording}
|
||||
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.eventMux, vmConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Warn("Wrote default Ethereum genesis block")
|
||||
// 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)
|
||||
eth.blockchain.SetHead(compat.RewindTo)
|
||||
core.WriteChainConfig(chainDb, genesisHash, chainConfig)
|
||||
}
|
||||
|
||||
if config.ChainConfig == nil {
|
||||
return nil, errors.New("missing chain config")
|
||||
}
|
||||
core.WriteChainConfig(chainDb, genesis.Hash(), config.ChainConfig)
|
||||
|
||||
eth.chainConfig = config.ChainConfig
|
||||
|
||||
log.Info("Initialised chain configuration", "config", eth.chainConfig)
|
||||
|
||||
eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.EventMux(), vm.Config{EnablePreimageRecording: config.EnablePreimageRecording})
|
||||
if err != nil {
|
||||
if err == core.ErrNoGenesis {
|
||||
return nil, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit)
|
||||
eth.txPool = newPool
|
||||
|
||||
@ -255,29 +241,6 @@ func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Data
|
||||
return db, err
|
||||
}
|
||||
|
||||
// SetupGenesisBlock initializes the genesis block for an Ethereum service
|
||||
func SetupGenesisBlock(chainDb *ethdb.Database, config *Config) error {
|
||||
// Load up any custom genesis block if requested
|
||||
if len(config.Genesis) > 0 {
|
||||
block, err := core.WriteGenesisBlock(*chainDb, strings.NewReader(config.Genesis))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Successfully wrote custom genesis block", "hash", block.Hash())
|
||||
}
|
||||
// Load up a test setup if directly injected
|
||||
if config.TestGenesisState != nil {
|
||||
*chainDb = config.TestGenesisState
|
||||
}
|
||||
if config.TestGenesisBlock != nil {
|
||||
core.WriteTd(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64(), config.TestGenesisBlock.Difficulty())
|
||||
core.WriteBlock(*chainDb, config.TestGenesisBlock)
|
||||
core.WriteCanonicalHash(*chainDb, config.TestGenesisBlock.Hash(), config.TestGenesisBlock.NumberU64())
|
||||
core.WriteHeadBlockHash(*chainDb, config.TestGenesisBlock.Hash())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreatePoW creates the required type of PoW instance for an Ethereum service
|
||||
func CreatePoW(ctx *node.ServiceContext, config *Config) pow.PoW {
|
||||
switch {
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
func TestMipmapUpgrade(t *testing.T) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
addr := common.BytesToAddress([]byte("jeff"))
|
||||
genesis := core.WriteGenesisBlockForTesting(db)
|
||||
genesis := new(core.Genesis).MustCommit(db)
|
||||
|
||||
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) {
|
||||
var receipts types.Receipts
|
||||
|
@ -76,8 +76,7 @@ func TestBlockSubscription(t *testing.T) {
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
backend = &testBackend{mux, db}
|
||||
api = NewPublicFilterAPI(backend, false)
|
||||
|
||||
genesis = core.WriteGenesisBlockForTesting(db)
|
||||
genesis = new(core.Genesis).MustCommit(db)
|
||||
chain, _ = core.GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *core.BlockGen) {})
|
||||
chainEvents = []core.ChainEvent{}
|
||||
)
|
||||
|
@ -60,7 +60,7 @@ func BenchmarkMipmaps(b *testing.B) {
|
||||
)
|
||||
defer db.Close()
|
||||
|
||||
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000)})
|
||||
genesis := core.GenesisBlockForTesting(db, addr1, big.NewInt(1000000))
|
||||
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 100010, func(i int, gen *core.BlockGen) {
|
||||
var receipts types.Receipts
|
||||
switch i {
|
||||
@ -112,7 +112,7 @@ func BenchmarkMipmaps(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
logs, _ := filter.Find(context.Background())
|
||||
if len(logs) != 4 {
|
||||
b.Fatal("expected 4 log, got", len(logs))
|
||||
b.Fatal("expected 4 logs, got", len(logs))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -138,7 +138,7 @@ func TestFilters(t *testing.T) {
|
||||
)
|
||||
defer db.Close()
|
||||
|
||||
genesis := core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000)})
|
||||
genesis := core.GenesisBlockForTesting(db, addr, big.NewInt(1000000))
|
||||
chain, receipts := core.GenerateChain(params.TestChainConfig, genesis, db, 1000, func(i int, gen *core.BlockGen) {
|
||||
var receipts types.Receipts
|
||||
switch i {
|
||||
|
@ -315,12 +315,12 @@ func testGetNodeData(t *testing.T, protocol int) {
|
||||
switch i {
|
||||
case 0:
|
||||
// In block 1, the test bank sends account #1 some ether.
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
block.AddTx(tx)
|
||||
case 1:
|
||||
// In block 2, the test bank sends some more ether to account #1.
|
||||
// acc1Addr passes it on to account #2.
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
|
||||
block.AddTx(tx1)
|
||||
block.AddTx(tx2)
|
||||
@ -372,7 +372,7 @@ func testGetNodeData(t *testing.T, protocol int) {
|
||||
for i := 0; i < len(data); i++ {
|
||||
statedb.Put(hashes[i].Bytes(), data[i])
|
||||
}
|
||||
accounts := []common.Address{testBank.Address, acc1Addr, acc2Addr}
|
||||
accounts := []common.Address{testBank, acc1Addr, acc2Addr}
|
||||
for i := uint64(0); i <= pm.blockchain.CurrentBlock().NumberU64(); i++ {
|
||||
trie, _ := state.New(pm.blockchain.GetBlockByNumber(i).Root(), statedb)
|
||||
|
||||
@ -407,12 +407,12 @@ func testGetReceipt(t *testing.T, protocol int) {
|
||||
switch i {
|
||||
case 0:
|
||||
// In block 1, the test bank sends account #1 some ether.
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(10000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
block.AddTx(tx)
|
||||
case 1:
|
||||
// In block 2, the test bank sends some more ether to account #1.
|
||||
// acc1Addr passes it on to account #2.
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank.Address), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx1, _ := types.SignTx(types.NewTransaction(block.TxNonce(testBank), acc1Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, testBankKey)
|
||||
tx2, _ := types.SignTx(types.NewTransaction(block.TxNonce(acc1Addr), acc2Addr, big.NewInt(1000), bigTxGas, nil, nil), signer, acc1Key)
|
||||
block.AddTx(tx1)
|
||||
block.AddTx(tx2)
|
||||
@ -471,8 +471,9 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool
|
||||
evmux = new(event.TypeMux)
|
||||
pow = new(pow.FakePow)
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
genesis = core.WriteGenesisBlockForTesting(db)
|
||||
config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked}
|
||||
gspec = &core.Genesis{Config: config}
|
||||
genesis = gspec.MustCommit(db)
|
||||
blockchain, _ = core.NewBlockChain(db, config, pow, evmux, vm.Config{})
|
||||
)
|
||||
pm, err := NewProtocolManager(config, false, NetworkId, 1000, evmux, new(testTxPool), pow, blockchain, db)
|
||||
|
@ -42,10 +42,7 @@ import (
|
||||
|
||||
var (
|
||||
testBankKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
testBank = core.GenesisAccount{
|
||||
Address: crypto.PubkeyToAddress(testBankKey.PublicKey),
|
||||
Balance: big.NewInt(1000000),
|
||||
}
|
||||
testBank = crypto.PubkeyToAddress(testBankKey.PublicKey)
|
||||
)
|
||||
|
||||
// newTestProtocolManager creates a new protocol manager for testing purposes,
|
||||
@ -56,16 +53,19 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core
|
||||
evmux = new(event.TypeMux)
|
||||
pow = new(pow.FakePow)
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
genesis = core.WriteGenesisBlockForTesting(db, testBank)
|
||||
chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
||||
blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux, vm.Config{})
|
||||
gspec = &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{testBank: {Balance: big.NewInt(1000000)}},
|
||||
}
|
||||
genesis = gspec.MustCommit(db)
|
||||
blockchain, _ = core.NewBlockChain(db, gspec.Config, pow, evmux, vm.Config{})
|
||||
)
|
||||
chain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
||||
chain, _ := core.GenerateChain(gspec.Config, genesis, db, blocks, generator)
|
||||
if _, err := blockchain.InsertChain(chain); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pm, err := NewProtocolManager(chainConfig, fastSync, NetworkId, 1000, evmux, &testTxPool{added: newtx}, pow, blockchain, db)
|
||||
pm, err := NewProtocolManager(gspec.Config, fastSync, NetworkId, 1000, evmux, &testTxPool{added: newtx}, pow, blockchain, db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
package les
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@ -74,15 +73,19 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := eth.SetupGenesisBlock(&chainDb, config); err != nil {
|
||||
return nil, err
|
||||
chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis)
|
||||
if _, isCompat := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !isCompat {
|
||||
return nil, genesisErr
|
||||
}
|
||||
log.Info("Initialised chain configuration", "config", chainConfig)
|
||||
|
||||
odr := NewLesOdr(chainDb)
|
||||
relay := NewLesTxRelay()
|
||||
eth := &LightEthereum{
|
||||
odr: odr,
|
||||
relay: relay,
|
||||
chainDb: chainDb,
|
||||
chainConfig: chainConfig,
|
||||
eventMux: ctx.EventMux,
|
||||
accountManager: ctx.AccountManager,
|
||||
pow: eth.CreatePoW(ctx, config),
|
||||
@ -91,17 +94,16 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||
solcPath: config.SolcPath,
|
||||
}
|
||||
|
||||
if config.ChainConfig == nil {
|
||||
return nil, errors.New("missing chain config")
|
||||
}
|
||||
eth.chainConfig = config.ChainConfig
|
||||
eth.blockchain, err = light.NewLightChain(odr, eth.chainConfig, eth.pow, eth.eventMux)
|
||||
if err != nil {
|
||||
if err == core.ErrNoGenesis {
|
||||
return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
// 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)
|
||||
eth.blockchain.SetHead(compat.RewindTo)
|
||||
core.WriteChainConfig(chainDb, genesisHash, chainConfig)
|
||||
}
|
||||
|
||||
eth.txPool = light.NewTxPool(eth.chainConfig, eth.eventMux, eth.blockchain, eth.relay)
|
||||
if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.LightMode, config.NetworkId, eth.eventMux, eth.pow, eth.blockchain, nil, chainDb, odr, relay); err != nil {
|
||||
|
@ -137,25 +137,28 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
|
||||
evmux = new(event.TypeMux)
|
||||
pow = new(pow.FakePow)
|
||||
db, _ = ethdb.NewMemDatabase()
|
||||
genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||
chainConfig = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker
|
||||
gspec = core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}},
|
||||
}
|
||||
genesis = gspec.MustCommit(db)
|
||||
odr *LesOdr
|
||||
chain BlockChain
|
||||
)
|
||||
|
||||
if lightSync {
|
||||
odr = NewLesOdr(db)
|
||||
chain, _ = light.NewLightChain(odr, chainConfig, pow, evmux)
|
||||
chain, _ = light.NewLightChain(odr, gspec.Config, pow, evmux)
|
||||
} else {
|
||||
blockchain, _ := core.NewBlockChain(db, chainConfig, pow, evmux, vm.Config{})
|
||||
gchain, _ := core.GenerateChain(chainConfig, genesis, db, blocks, generator)
|
||||
blockchain, _ := core.NewBlockChain(db, gspec.Config, pow, evmux, vm.Config{})
|
||||
gchain, _ := core.GenerateChain(gspec.Config, genesis, db, blocks, generator)
|
||||
if _, err := blockchain.InsertChain(gchain); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
chain = blockchain
|
||||
}
|
||||
|
||||
pm, err := NewProtocolManager(chainConfig, lightSync, NetworkId, evmux, pow, chain, nil, db, odr, nil)
|
||||
pm, err := NewProtocolManager(gspec.Config, lightSync, NetworkId, evmux, pow, chain, nil, db, odr, nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ type LesServer struct {
|
||||
}
|
||||
|
||||
func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||
pm, err := NewProtocolManager(config.ChainConfig, false, config.NetworkId, eth.EventMux(), eth.Pow(), eth.BlockChain(), eth.TxPool(), eth.ChainDb(), nil, nil)
|
||||
pm, err := NewProtocolManager(eth.BlockChain().Config(), false, config.NetworkId, eth.EventMux(), eth.Pow(), eth.BlockChain(), eth.TxPool(), eth.ChainDb(), nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -96,11 +96,7 @@ func NewLightChain(odr OdrBackend, config *params.ChainConfig, pow pow.PoW, mux
|
||||
|
||||
bc.genesisBlock, _ = bc.GetBlockByNumber(NoOdr, 0)
|
||||
if bc.genesisBlock == nil {
|
||||
bc.genesisBlock, err = core.WriteDefaultGenesisBlock(odr.Database())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Warn("Wrote default ethereum genesis block")
|
||||
return nil, core.ErrNoGenesis
|
||||
}
|
||||
|
||||
if bc.genesisBlock.Hash() == params.MainNetGenesisHash {
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -30,7 +29,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// So we can deterministically seed different blockchains
|
||||
@ -59,14 +57,10 @@ func testChainConfig() *params.ChainConfig {
|
||||
// chain. Depending on the full flag, if creates either a full block chain or a
|
||||
// header only chain.
|
||||
func newCanonical(n int) (ethdb.Database, *LightChain, error) {
|
||||
// Create te new chain database
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
evmux := &event.TypeMux{}
|
||||
|
||||
// Initialize a fresh chain with only a genesis block
|
||||
genesis, _ := core.WriteTestNetGenesisBlock(db)
|
||||
|
||||
blockchain, _ := NewLightChain(&dummyOdr{db: db}, testChainConfig(), pow.FakePow{}, evmux)
|
||||
gspec := core.Genesis{Config: testChainConfig()}
|
||||
genesis := gspec.MustCommit(db)
|
||||
blockchain, _ := NewLightChain(&dummyOdr{db: db}, gspec.Config, pow.FakePow{}, new(event.TypeMux))
|
||||
// Create and inject the requested chain
|
||||
if n == 0 {
|
||||
return db, blockchain, nil
|
||||
@ -77,21 +71,20 @@ func newCanonical(n int) (ethdb.Database, *LightChain, error) {
|
||||
return db, blockchain, err
|
||||
}
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
||||
|
||||
func theLightChain(db ethdb.Database, t *testing.T) *LightChain {
|
||||
var eventMux event.TypeMux
|
||||
core.WriteTestNetGenesisBlock(db)
|
||||
LightChain, err := NewLightChain(&dummyOdr{db: db}, testChainConfig(), pow.NewTestEthash(), &eventMux)
|
||||
if err != nil {
|
||||
t.Error("failed creating LightChain:", err)
|
||||
t.FailNow()
|
||||
return nil
|
||||
// newTestLightChain creates a LightChain that doesn't validate anything.
|
||||
func newTestLightChain() *LightChain {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
gspec := &core.Genesis{
|
||||
Difficulty: big.NewInt(1),
|
||||
Config: testChainConfig(),
|
||||
}
|
||||
|
||||
return LightChain
|
||||
gspec.MustCommit(db)
|
||||
lc, err := NewLightChain(&dummyOdr{db: db}, gspec.Config, pow.NewTestEthash(), new(event.TypeMux))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
lc.SetValidator(bproc{})
|
||||
return lc
|
||||
}
|
||||
|
||||
// Test fork of length N starting from block i
|
||||
@ -302,20 +295,6 @@ func (odr *dummyOdr) Retrieve(ctx context.Context, req OdrRequest) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func chm(genesis *types.Block, db ethdb.Database) *LightChain {
|
||||
odr := &dummyOdr{db: db}
|
||||
var eventMux event.TypeMux
|
||||
bc := &LightChain{odr: odr, chainDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: pow.FakePow{}}
|
||||
bc.hc, _ = core.NewHeaderChain(db, testChainConfig(), bc.Validator, bc.getProcInterrupt)
|
||||
bc.bodyCache, _ = lru.New(100)
|
||||
bc.bodyRLPCache, _ = lru.New(100)
|
||||
bc.blockCache, _ = lru.New(100)
|
||||
bc.SetValidator(bproc{})
|
||||
bc.ResetWithGenesisBlock(genesis)
|
||||
|
||||
return bc
|
||||
}
|
||||
|
||||
// Tests that reorganizing a long difficult chain after a short easy one
|
||||
// overwrites the canonical numbers and links in the database.
|
||||
func TestReorgLongHeaders(t *testing.T) {
|
||||
@ -329,14 +308,11 @@ func TestReorgShortHeaders(t *testing.T) {
|
||||
}
|
||||
|
||||
func testReorg(t *testing.T, first, second []int, td int64) {
|
||||
// Create a pristine block chain
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis, _ := core.WriteTestNetGenesisBlock(db)
|
||||
bc := chm(genesis, db)
|
||||
bc := newTestLightChain()
|
||||
|
||||
// Insert an easy and a difficult chain afterwards
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, first, 11), 1)
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, second, 22), 1)
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1)
|
||||
bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1)
|
||||
// Check that the chain is valid number and link wise
|
||||
prev := bc.CurrentHeader()
|
||||
for header := bc.GetHeaderByNumber(bc.CurrentHeader().Number.Uint64() - 1); header.Number.Uint64() != 0; prev, header = header, bc.GetHeaderByNumber(header.Number.Uint64()-1) {
|
||||
@ -345,7 +321,7 @@ func testReorg(t *testing.T, first, second []int, td int64) {
|
||||
}
|
||||
}
|
||||
// Make sure the chain total difficulty is the correct one
|
||||
want := new(big.Int).Add(genesis.Difficulty(), big.NewInt(td))
|
||||
want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td))
|
||||
if have := bc.GetTdByHash(bc.CurrentHeader().Hash()); have.Cmp(want) != 0 {
|
||||
t.Errorf("total difficulty mismatch: have %v, want %v", have, want)
|
||||
}
|
||||
@ -353,14 +329,11 @@ func testReorg(t *testing.T, first, second []int, td int64) {
|
||||
|
||||
// Tests that the insertion functions detect banned hashes.
|
||||
func TestBadHeaderHashes(t *testing.T) {
|
||||
// Create a pristine block chain
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis, _ := core.WriteTestNetGenesisBlock(db)
|
||||
bc := chm(genesis, db)
|
||||
bc := newTestLightChain()
|
||||
|
||||
// Create a chain, ban a hash and try to import
|
||||
var err error
|
||||
headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 4}, 10)
|
||||
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
|
||||
core.BadHashes[headers[2].Hash()] = true
|
||||
_, err = bc.InsertHeaderChain(headers, 1)
|
||||
if !core.IsBadHashError(err) {
|
||||
@ -371,13 +344,10 @@ func TestBadHeaderHashes(t *testing.T) {
|
||||
// Tests that bad hashes are detected on boot, and the chan rolled back to a
|
||||
// good state prior to the bad hash.
|
||||
func TestReorgBadHeaderHashes(t *testing.T) {
|
||||
// Create a pristine block chain
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
genesis, _ := core.WriteTestNetGenesisBlock(db)
|
||||
bc := chm(genesis, db)
|
||||
bc := newTestLightChain()
|
||||
|
||||
// Create a chain, import and ban aferwards
|
||||
headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
|
||||
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
|
||||
|
||||
if _, err := bc.InsertHeaderChain(headers, 1); err != nil {
|
||||
t.Fatalf("failed to import headers: %v", err)
|
||||
@ -387,8 +357,9 @@ func TestReorgBadHeaderHashes(t *testing.T) {
|
||||
}
|
||||
core.BadHashes[headers[3].Hash()] = true
|
||||
defer func() { delete(core.BadHashes, headers[3].Hash()) }()
|
||||
// Create a new chain manager and check it rolled back the state
|
||||
ncm, err := NewLightChain(&dummyOdr{db: db}, testChainConfig(), pow.FakePow{}, new(event.TypeMux))
|
||||
|
||||
// Create a new LightChain and check that it rolled back the state.
|
||||
ncm, err := NewLightChain(&dummyOdr{db: bc.chainDb}, testChainConfig(), pow.FakePow{}, new(event.TypeMux))
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create new chain manager: %v", err)
|
||||
}
|
||||
|
@ -251,9 +251,10 @@ func testChainOdr(t *testing.T, protocol int, expFail uint64, fn odrTestFn) {
|
||||
pow = new(pow.FakePow)
|
||||
sdb, _ = ethdb.NewMemDatabase()
|
||||
ldb, _ = ethdb.NewMemDatabase()
|
||||
genesis = core.WriteGenesisBlockForTesting(sdb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||
gspec = core.Genesis{Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}}
|
||||
genesis = gspec.MustCommit(sdb)
|
||||
)
|
||||
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||
gspec.MustCommit(ldb)
|
||||
// Assemble the test environment
|
||||
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux, vm.Config{})
|
||||
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
||||
|
@ -86,9 +86,10 @@ func TestTxPool(t *testing.T) {
|
||||
pow = new(pow.FakePow)
|
||||
sdb, _ = ethdb.NewMemDatabase()
|
||||
ldb, _ = ethdb.NewMemDatabase()
|
||||
genesis = core.WriteGenesisBlockForTesting(sdb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||
gspec = core.Genesis{Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}}
|
||||
genesis = gspec.MustCommit(sdb)
|
||||
)
|
||||
core.WriteGenesisBlockForTesting(ldb, core.GenesisAccount{Address: testBankAddress, Balance: testBankFunds})
|
||||
gspec.MustCommit(ldb)
|
||||
// Assemble the test environment
|
||||
blockchain, _ := core.NewBlockChain(sdb, testChainConfig(), pow, evmux, vm.Config{})
|
||||
chainConfig := ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}
|
||||
|
@ -20,10 +20,12 @@
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/ethstats"
|
||||
@ -92,6 +94,18 @@ func NewNodeConfig() *NodeConfig {
|
||||
return &config
|
||||
}
|
||||
|
||||
// SetMainnet sets up the node for use on the Ethereum mainnet.
|
||||
func (cfg *NodeConfig) SetMainnet() {
|
||||
cfg.EthereumGenesis = ""
|
||||
cfg.EthereumChainConfig = MainnetChainConfig()
|
||||
}
|
||||
|
||||
// SetTestnet sets up the node for use on the Ethereum testnet.
|
||||
func (cfg *NodeConfig) SetTestnet() {
|
||||
cfg.EthereumGenesis = TestnetGenesis()
|
||||
cfg.EthereumChainConfig = TestnetChainConfig()
|
||||
}
|
||||
|
||||
// Node represents a Geth Ethereum node instance.
|
||||
type Node struct {
|
||||
node *node.Node
|
||||
@ -127,10 +141,19 @@ func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Register the Ethereum protocol if requested
|
||||
if config.EthereumEnabled {
|
||||
ethConf := ð.Config{
|
||||
ChainConfig: ¶ms.ChainConfig{
|
||||
|
||||
var genesis *core.Genesis
|
||||
if config.EthereumGenesis != "" {
|
||||
genesis = new(core.Genesis)
|
||||
if err := json.Unmarshal([]byte(config.EthereumGenesis), genesis); err != nil {
|
||||
return nil, fmt.Errorf("invalid EthereumGenesis: %v", err)
|
||||
}
|
||||
}
|
||||
if config.EthereumChainConfig != nil {
|
||||
if genesis == nil {
|
||||
genesis = core.DefaultGenesisBlock()
|
||||
}
|
||||
genesis.Config = ¶ms.ChainConfig{
|
||||
ChainId: big.NewInt(config.EthereumChainConfig.ChainID),
|
||||
HomesteadBlock: big.NewInt(config.EthereumChainConfig.HomesteadBlock),
|
||||
DAOForkBlock: big.NewInt(config.EthereumChainConfig.DAOForkBlock),
|
||||
@ -139,8 +162,13 @@ func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) {
|
||||
EIP150Hash: config.EthereumChainConfig.EIP150Hash.hash,
|
||||
EIP155Block: big.NewInt(config.EthereumChainConfig.EIP155Block),
|
||||
EIP158Block: big.NewInt(config.EthereumChainConfig.EIP158Block),
|
||||
},
|
||||
Genesis: config.EthereumGenesis,
|
||||
}
|
||||
}
|
||||
|
||||
// Register the Ethereum protocol if requested
|
||||
if config.EthereumEnabled {
|
||||
ethConf := ð.Config{
|
||||
Genesis: genesis,
|
||||
LightMode: true,
|
||||
DatabaseCache: config.EthereumDatabaseCache,
|
||||
NetworkId: config.EthereumNetworkID,
|
||||
|
@ -19,6 +19,8 @@
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/p2p/discv5"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
@ -60,7 +62,11 @@ func TestnetChainConfig() *ChainConfig {
|
||||
|
||||
// TestnetGenesis returns the JSON spec to use for the Ethereum test network.
|
||||
func TestnetGenesis() string {
|
||||
return core.DefaultTestnetGenesisBlock()
|
||||
enc, err := json.Marshal(core.DefaultTestnetGenesisBlock())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(enc)
|
||||
}
|
||||
|
||||
// ChainConfig is the core config which determines the blockchain settings.
|
||||
|
180
params/config.go
180
params/config.go
@ -23,8 +23,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// MainnetChainConfig is the chain parameters to run a node on the main network.
|
||||
var MainnetChainConfig = &ChainConfig{
|
||||
var (
|
||||
// MainnetChainConfig is the chain parameters to run a node on the main network.
|
||||
MainnetChainConfig = &ChainConfig{
|
||||
ChainId: MainNetChainID,
|
||||
HomesteadBlock: MainNetHomesteadBlock,
|
||||
DAOForkBlock: MainNetDAOForkBlock,
|
||||
@ -33,10 +34,10 @@ var MainnetChainConfig = &ChainConfig{
|
||||
EIP150Hash: MainNetHomesteadGasRepriceHash,
|
||||
EIP155Block: MainNetSpuriousDragon,
|
||||
EIP158Block: MainNetSpuriousDragon,
|
||||
}
|
||||
}
|
||||
|
||||
// TestnetChainConfig is the chain parameters to run a node on the test network.
|
||||
var TestnetChainConfig = &ChainConfig{
|
||||
// TestnetChainConfig contains the chain parameters to run a node on the ropsten test network.
|
||||
TestnetChainConfig = &ChainConfig{
|
||||
ChainId: big.NewInt(3),
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
DAOForkBlock: nil,
|
||||
@ -45,17 +46,20 @@ var TestnetChainConfig = &ChainConfig{
|
||||
EIP150Hash: common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d"),
|
||||
EIP155Block: big.NewInt(10),
|
||||
EIP158Block: big.NewInt(10),
|
||||
}
|
||||
}
|
||||
|
||||
// AllProtocolChanges contains every protocol change (EIPs)
|
||||
// introduced and accepted by the Ethereum core developers.
|
||||
//
|
||||
// This configuration is intentionally not using keyed fields.
|
||||
// This configuration must *always* have all forks enabled, which
|
||||
// means that all fields must be set at all times. This forces
|
||||
// anyone adding flags to the config to also have to set these
|
||||
// fields.
|
||||
var AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0)}
|
||||
// AllProtocolChanges contains every protocol change (EIPs)
|
||||
// introduced and accepted by the Ethereum core developers.
|
||||
// TestChainConfig is like AllProtocolChanges but has chain ID 1.
|
||||
//
|
||||
// This configuration is intentionally not using keyed fields.
|
||||
// This configuration must *always* have all forks enabled, which
|
||||
// means that all fields must be set at all times. This forces
|
||||
// anyone adding flags to the config to also have to set these
|
||||
// fields.
|
||||
AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0)}
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0)}
|
||||
)
|
||||
|
||||
// ChainConfig is the core config which determines the blockchain settings.
|
||||
//
|
||||
@ -77,7 +81,7 @@ type ChainConfig struct {
|
||||
EIP158Block *big.Int `json:"eip158Block"` // EIP158 HF block
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
// String implements the fmt.Stringer interface.
|
||||
func (c *ChainConfig) String() string {
|
||||
return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v}",
|
||||
c.ChainId,
|
||||
@ -90,17 +94,26 @@ func (c *ChainConfig) String() string {
|
||||
)
|
||||
}
|
||||
|
||||
var (
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), new(big.Int), new(big.Int), true, new(big.Int), common.Hash{}, new(big.Int), new(big.Int)}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||
)
|
||||
|
||||
// IsHomestead returns whether num is either equal to the homestead block or greater.
|
||||
func (c *ChainConfig) IsHomestead(num *big.Int) bool {
|
||||
if c.HomesteadBlock == nil || num == nil {
|
||||
return false
|
||||
}
|
||||
return num.Cmp(c.HomesteadBlock) >= 0
|
||||
return isForked(c.HomesteadBlock, num)
|
||||
}
|
||||
|
||||
// IsDAO returns whether num is either equal to the DAO fork block or greater.
|
||||
func (c *ChainConfig) IsDAOFork(num *big.Int) bool {
|
||||
return isForked(c.DAOForkBlock, num)
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP150(num *big.Int) bool {
|
||||
return isForked(c.EIP150Block, num)
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP155(num *big.Int) bool {
|
||||
return isForked(c.EIP155Block, num)
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP158(num *big.Int) bool {
|
||||
return isForked(c.EIP158Block, num)
|
||||
}
|
||||
|
||||
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
|
||||
@ -110,51 +123,110 @@ func (c *ChainConfig) GasTable(num *big.Int) GasTable {
|
||||
if num == nil {
|
||||
return GasTableHomestead
|
||||
}
|
||||
|
||||
switch {
|
||||
case c.EIP158Block != nil && num.Cmp(c.EIP158Block) >= 0:
|
||||
case c.IsEIP158(num):
|
||||
return GasTableEIP158
|
||||
case c.EIP150Block != nil && num.Cmp(c.EIP150Block) >= 0:
|
||||
case c.IsEIP150(num):
|
||||
return GasTableHomesteadGasRepriceFork
|
||||
default:
|
||||
return GasTableHomestead
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP150(num *big.Int) bool {
|
||||
if c.EIP150Block == nil || num == nil {
|
||||
// CheckCompatible checks whether scheduled fork transitions have been imported
|
||||
// with a mismatching chain configuration.
|
||||
func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64) *ConfigCompatError {
|
||||
bhead := new(big.Int).SetUint64(height)
|
||||
|
||||
// Iterate checkCompatible to find the lowest conflict.
|
||||
var lasterr *ConfigCompatError
|
||||
for {
|
||||
err := c.checkCompatible(newcfg, bhead)
|
||||
if err == nil || (lasterr != nil && err.RewindTo == lasterr.RewindTo) {
|
||||
break
|
||||
}
|
||||
lasterr = err
|
||||
bhead.SetUint64(err.RewindTo)
|
||||
}
|
||||
return lasterr
|
||||
}
|
||||
|
||||
func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *ConfigCompatError {
|
||||
if isForkIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, head) {
|
||||
return newCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock)
|
||||
}
|
||||
if isForkIncompatible(c.DAOForkBlock, newcfg.DAOForkBlock, head) {
|
||||
return newCompatError("DAO fork block", c.DAOForkBlock, newcfg.DAOForkBlock)
|
||||
}
|
||||
if c.IsDAOFork(head) && c.DAOForkSupport != newcfg.DAOForkSupport {
|
||||
return newCompatError("DAO fork support flag", c.DAOForkBlock, newcfg.DAOForkBlock)
|
||||
}
|
||||
if isForkIncompatible(c.EIP150Block, newcfg.EIP150Block, head) {
|
||||
return newCompatError("EIP150 fork block", c.EIP150Block, newcfg.EIP150Block)
|
||||
}
|
||||
if isForkIncompatible(c.EIP155Block, newcfg.EIP155Block, head) {
|
||||
return newCompatError("EIP155 fork block", c.EIP155Block, newcfg.EIP155Block)
|
||||
}
|
||||
if isForkIncompatible(c.EIP158Block, newcfg.EIP158Block, head) {
|
||||
return newCompatError("EIP158 fork block", c.EIP158Block, newcfg.EIP158Block)
|
||||
}
|
||||
if c.IsEIP158(head) && !configNumEqual(c.ChainId, newcfg.ChainId) {
|
||||
return newCompatError("EIP158 chain ID", c.EIP158Block, newcfg.EIP158Block)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// isForkIncompatible returns true if a fork scheduled at s1 cannot be rescheduled to
|
||||
// block s2 because head is already past the fork.
|
||||
func isForkIncompatible(s1, s2, head *big.Int) bool {
|
||||
return (isForked(s1, head) || isForked(s2, head)) && !configNumEqual(s1, s2)
|
||||
}
|
||||
|
||||
// isForked returns whether a fork scheduled at block s is active at the given head block.
|
||||
func isForked(s, head *big.Int) bool {
|
||||
if s == nil || head == nil {
|
||||
return false
|
||||
}
|
||||
return num.Cmp(c.EIP150Block) >= 0
|
||||
|
||||
return s.Cmp(head) <= 0
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP155(num *big.Int) bool {
|
||||
if c.EIP155Block == nil || num == nil {
|
||||
return false
|
||||
func configNumEqual(x, y *big.Int) bool {
|
||||
if x == nil {
|
||||
return y == nil
|
||||
}
|
||||
return num.Cmp(c.EIP155Block) >= 0
|
||||
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP158(num *big.Int) bool {
|
||||
if c.EIP158Block == nil || num == nil {
|
||||
return false
|
||||
if y == nil {
|
||||
return x == nil
|
||||
}
|
||||
return num.Cmp(c.EIP158Block) >= 0
|
||||
|
||||
return x.Cmp(y) == 0
|
||||
}
|
||||
|
||||
// Rules wraps ChainConfig and is merely syntatic sugar or can be used for functions
|
||||
// that do not have or require information about the block.
|
||||
//
|
||||
// Rules is a one time interface meaning that it shouldn't be used in between transition
|
||||
// phases.
|
||||
type Rules struct {
|
||||
ChainId *big.Int
|
||||
IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool
|
||||
// ConfigCompatError is raised if the locally-stored blockchain is initialised with a
|
||||
// ChainConfig that would alter the past.
|
||||
type ConfigCompatError struct {
|
||||
What string
|
||||
// block numbers of the stored and new configurations
|
||||
StoredConfig, NewConfig *big.Int
|
||||
// the block number to which the local chain must be rewound to correct the error
|
||||
RewindTo uint64
|
||||
}
|
||||
|
||||
func (c *ChainConfig) Rules(num *big.Int) Rules {
|
||||
return Rules{ChainId: new(big.Int).Set(c.ChainId), IsHomestead: c.IsHomestead(num), IsEIP150: c.IsEIP150(num), IsEIP155: c.IsEIP155(num), IsEIP158: c.IsEIP158(num)}
|
||||
func newCompatError(what string, storedblock, newblock *big.Int) *ConfigCompatError {
|
||||
var rew *big.Int
|
||||
switch {
|
||||
case storedblock == nil:
|
||||
rew = newblock
|
||||
case newblock == nil || storedblock.Cmp(newblock) < 0:
|
||||
rew = storedblock
|
||||
default:
|
||||
rew = newblock
|
||||
}
|
||||
err := &ConfigCompatError{what, storedblock, newblock, 0}
|
||||
if rew != nil && rew.Sign() > 0 {
|
||||
err.RewindTo = rew.Uint64() - 1
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (err *ConfigCompatError) Error() string {
|
||||
return fmt.Sprintf("mismatching %s in database (have %d, want %d, rewindto %d)", err.What, err.StoredConfig, err.NewConfig, err.RewindTo)
|
||||
}
|
||||
|
81
params/config_test.go
Normal file
81
params/config_test.go
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright 2017 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 params
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCheckCompatible(t *testing.T) {
|
||||
type test struct {
|
||||
stored, new *ChainConfig
|
||||
head uint64
|
||||
wantErr *ConfigCompatError
|
||||
}
|
||||
tests := []test{
|
||||
{stored: AllProtocolChanges, new: AllProtocolChanges, head: 0, wantErr: nil},
|
||||
{stored: AllProtocolChanges, new: AllProtocolChanges, head: 100, wantErr: nil},
|
||||
{
|
||||
stored: &ChainConfig{EIP150Block: big.NewInt(10)},
|
||||
new: &ChainConfig{EIP150Block: big.NewInt(20)},
|
||||
head: 9,
|
||||
wantErr: nil,
|
||||
},
|
||||
{
|
||||
stored: AllProtocolChanges,
|
||||
new: &ChainConfig{HomesteadBlock: nil},
|
||||
head: 3,
|
||||
wantErr: &ConfigCompatError{
|
||||
What: "Homestead fork block",
|
||||
StoredConfig: big.NewInt(0),
|
||||
NewConfig: nil,
|
||||
RewindTo: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
stored: AllProtocolChanges,
|
||||
new: &ChainConfig{HomesteadBlock: big.NewInt(1)},
|
||||
head: 3,
|
||||
wantErr: &ConfigCompatError{
|
||||
What: "Homestead fork block",
|
||||
StoredConfig: big.NewInt(0),
|
||||
NewConfig: big.NewInt(1),
|
||||
RewindTo: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
stored: &ChainConfig{HomesteadBlock: big.NewInt(30), EIP150Block: big.NewInt(10)},
|
||||
new: &ChainConfig{HomesteadBlock: big.NewInt(25), EIP150Block: big.NewInt(20)},
|
||||
head: 25,
|
||||
wantErr: &ConfigCompatError{
|
||||
What: "EIP150 fork block",
|
||||
StoredConfig: big.NewInt(10),
|
||||
NewConfig: big.NewInt(20),
|
||||
RewindTo: 9,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
err := test.stored.CheckCompatible(test.new, test.head)
|
||||
if !reflect.DeepEqual(err, test.wantErr) {
|
||||
t.Errorf("error mismatch:\nstored: %v\nnew: %v\nhead: %v\nerr: %v\nwant: %v", test.stored, test.new, test.head, err, test.wantErr)
|
||||
}
|
||||
}
|
||||
}
|
487
params/dao.go
487
params/dao.go
@ -17,8 +17,6 @@
|
||||
package params
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -47,372 +45,123 @@ var DAORefundContract = common.HexToAddress("0xbf4ed7b27f1d666546e30d74d50d173d2
|
||||
|
||||
// DAODrainList is the list of accounts whose full balances will be moved into a
|
||||
// refund contract at the beginning of the dao-fork block.
|
||||
var DAODrainList []common.Address
|
||||
|
||||
func init() {
|
||||
// Parse the list of DAO accounts to drain
|
||||
var list []map[string]string
|
||||
if err := json.Unmarshal([]byte(daoDrainListJSON), &list); err != nil {
|
||||
panic(fmt.Errorf("Failed to parse DAO drain list: %v", err))
|
||||
}
|
||||
// Collect all the accounts that need draining
|
||||
for _, dao := range list {
|
||||
DAODrainList = append(DAODrainList, common.HexToAddress(dao["address"]))
|
||||
DAODrainList = append(DAODrainList, common.HexToAddress(dao["extraBalanceAccount"]))
|
||||
func DAODrainList() []common.Address {
|
||||
return []common.Address{
|
||||
common.HexToAddress("0xd4fe7bc31cedb7bfb8a345f31e668033056b2728"),
|
||||
common.HexToAddress("0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425"),
|
||||
common.HexToAddress("0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f"),
|
||||
common.HexToAddress("0xecd135fa4f61a655311e86238c92adcd779555d2"),
|
||||
common.HexToAddress("0x1975bd06d486162d5dc297798dfc41edd5d160a7"),
|
||||
common.HexToAddress("0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6"),
|
||||
common.HexToAddress("0x319f70bab6845585f412ec7724b744fec6095c85"),
|
||||
common.HexToAddress("0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936"),
|
||||
common.HexToAddress("0x5c8536898fbb74fc7445814902fd08422eac56d0"),
|
||||
common.HexToAddress("0x6966ab0d485353095148a2155858910e0965b6f9"),
|
||||
common.HexToAddress("0x779543a0491a837ca36ce8c635d6154e3c4911a6"),
|
||||
common.HexToAddress("0x2a5ed960395e2a49b1c758cef4aa15213cfd874c"),
|
||||
common.HexToAddress("0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5"),
|
||||
common.HexToAddress("0x9c50426be05db97f5d64fc54bf89eff947f0a321"),
|
||||
common.HexToAddress("0x200450f06520bdd6c527622a273333384d870efb"),
|
||||
common.HexToAddress("0xbe8539bfe837b67d1282b2b1d61c3f723966f049"),
|
||||
common.HexToAddress("0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb"),
|
||||
common.HexToAddress("0xf1385fb24aad0cd7432824085e42aff90886fef5"),
|
||||
common.HexToAddress("0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091"),
|
||||
common.HexToAddress("0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd"),
|
||||
common.HexToAddress("0x51e0ddd9998364a2eb38588679f0d2c42653e4a6"),
|
||||
common.HexToAddress("0x627a0a960c079c21c34f7612d5d230e01b4ad4c7"),
|
||||
common.HexToAddress("0xf0b1aa0eb660754448a7937c022e30aa692fe0c5"),
|
||||
common.HexToAddress("0x24c4d950dfd4dd1902bbed3508144a54542bba94"),
|
||||
common.HexToAddress("0x9f27daea7aca0aa0446220b98d028715e3bc803d"),
|
||||
common.HexToAddress("0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90"),
|
||||
common.HexToAddress("0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b"),
|
||||
common.HexToAddress("0x63ed5a272de2f6d968408b4acb9024f4cc208ebf"),
|
||||
common.HexToAddress("0x6f6704e5a10332af6672e50b3d9754dc460dfa4d"),
|
||||
common.HexToAddress("0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6"),
|
||||
common.HexToAddress("0x492ea3bb0f3315521c31f273e565b868fc090f17"),
|
||||
common.HexToAddress("0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00"),
|
||||
common.HexToAddress("0x9ea779f907f0b315b364b0cfc39a0fde5b02a416"),
|
||||
common.HexToAddress("0xceaeb481747ca6c540a000c1f3641f8cef161fa7"),
|
||||
common.HexToAddress("0xcc34673c6c40e791051898567a1222daf90be287"),
|
||||
common.HexToAddress("0x579a80d909f346fbfb1189493f521d7f48d52238"),
|
||||
common.HexToAddress("0xe308bd1ac5fda103967359b2712dd89deffb7973"),
|
||||
common.HexToAddress("0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c"),
|
||||
common.HexToAddress("0xac1ecab32727358dba8962a0f3b261731aad9723"),
|
||||
common.HexToAddress("0x4fd6ace747f06ece9c49699c7cabc62d02211f75"),
|
||||
common.HexToAddress("0x440c59b325d2997a134c2c7c60a8c61611212bad"),
|
||||
common.HexToAddress("0x4486a3d68fac6967006d7a517b889fd3f98c102b"),
|
||||
common.HexToAddress("0x9c15b54878ba618f494b38f0ae7443db6af648ba"),
|
||||
common.HexToAddress("0x27b137a85656544b1ccb5a0f2e561a5703c6a68f"),
|
||||
common.HexToAddress("0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241"),
|
||||
common.HexToAddress("0x23b75c2f6791eef49c69684db4c6c1f93bf49a50"),
|
||||
common.HexToAddress("0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b"),
|
||||
common.HexToAddress("0xb9637156d330c0d605a791f1c31ba5890582fe1c"),
|
||||
common.HexToAddress("0x6131c42fa982e56929107413a9d526fd99405560"),
|
||||
common.HexToAddress("0x1591fc0f688c81fbeb17f5426a162a7024d430c2"),
|
||||
common.HexToAddress("0x542a9515200d14b68e934e9830d91645a980dd7a"),
|
||||
common.HexToAddress("0xc4bbd073882dd2add2424cf47d35213405b01324"),
|
||||
common.HexToAddress("0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4"),
|
||||
common.HexToAddress("0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb"),
|
||||
common.HexToAddress("0x3ba4d81db016dc2890c81f3acec2454bff5aada5"),
|
||||
common.HexToAddress("0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab"),
|
||||
common.HexToAddress("0xe4ae1efdfc53b73893af49113d8694a057b9c0d1"),
|
||||
common.HexToAddress("0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5"),
|
||||
common.HexToAddress("0x0737a6b837f97f46ebade41b9bc3e1c509c85c53"),
|
||||
common.HexToAddress("0x97f43a37f595ab5dd318fb46e7a155eae057317a"),
|
||||
common.HexToAddress("0x52c5317c848ba20c7504cb2c8052abd1fde29d03"),
|
||||
common.HexToAddress("0x4863226780fe7c0356454236d3b1c8792785748d"),
|
||||
common.HexToAddress("0x5d2b2e6fcbe3b11d26b525e085ff818dae332479"),
|
||||
common.HexToAddress("0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c"),
|
||||
common.HexToAddress("0x057b56736d32b86616a10f619859c6cd6f59092a"),
|
||||
common.HexToAddress("0x9aa008f65de0b923a2a4f02012ad034a5e2e2192"),
|
||||
common.HexToAddress("0x304a554a310c7e546dfe434669c62820b7d83490"),
|
||||
common.HexToAddress("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79"),
|
||||
common.HexToAddress("0x4deb0033bb26bc534b197e61d19e0733e5679784"),
|
||||
common.HexToAddress("0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a"),
|
||||
common.HexToAddress("0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b"),
|
||||
common.HexToAddress("0x4fa802324e929786dbda3b8820dc7834e9134a2a"),
|
||||
common.HexToAddress("0x9da397b9e80755301a3b32173283a91c0ef6c87e"),
|
||||
common.HexToAddress("0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6"),
|
||||
common.HexToAddress("0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9"),
|
||||
common.HexToAddress("0x5dc28b15dffed94048d73806ce4b7a4612a1d48f"),
|
||||
common.HexToAddress("0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76"),
|
||||
common.HexToAddress("0x12e626b0eebfe86a56d633b9864e389b45dcb260"),
|
||||
common.HexToAddress("0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7"),
|
||||
common.HexToAddress("0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5"),
|
||||
common.HexToAddress("0xd164b088bd9108b60d0ca3751da4bceb207b0782"),
|
||||
common.HexToAddress("0x6231b6d0d5e77fe001c2a460bd9584fee60d409b"),
|
||||
common.HexToAddress("0x1cba23d343a983e9b5cfd19496b9a9701ada385f"),
|
||||
common.HexToAddress("0xa82f360a8d3455c5c41366975bde739c37bfeb8a"),
|
||||
common.HexToAddress("0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339"),
|
||||
common.HexToAddress("0x005f5cee7a43331d5a3d3eec71305925a62f34b6"),
|
||||
common.HexToAddress("0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d"),
|
||||
common.HexToAddress("0xd131637d5275fd1a68a3200f4ad25c71a2a9522e"),
|
||||
common.HexToAddress("0xbc07118b9ac290e4622f5e77a0853539789effbe"),
|
||||
common.HexToAddress("0x47e7aa56d6bdf3f36be34619660de61275420af8"),
|
||||
common.HexToAddress("0xacd87e28b0c9d1254e868b81cba4cc20d9a32225"),
|
||||
common.HexToAddress("0xadf80daec7ba8dcf15392f1ac611fff65d94f880"),
|
||||
common.HexToAddress("0x5524c55fb03cf21f549444ccbecb664d0acad706"),
|
||||
common.HexToAddress("0x40b803a9abce16f50f36a77ba41180eb90023925"),
|
||||
common.HexToAddress("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f"),
|
||||
common.HexToAddress("0x17802f43a0137c506ba92291391a8a8f207f487d"),
|
||||
common.HexToAddress("0x253488078a4edf4d6f42f113d1e62836a942cf1a"),
|
||||
common.HexToAddress("0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915"),
|
||||
common.HexToAddress("0xb136707642a4ea12fb4bae820f03d2562ebff487"),
|
||||
common.HexToAddress("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940"),
|
||||
common.HexToAddress("0xf14c14075d6c4ed84b86798af0956deef67365b5"),
|
||||
common.HexToAddress("0xca544e5c4687d109611d0f8f928b53a25af72448"),
|
||||
common.HexToAddress("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c"),
|
||||
common.HexToAddress("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7"),
|
||||
common.HexToAddress("0x6d87578288b6cb5549d5076a207456a1f6a63dc0"),
|
||||
common.HexToAddress("0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e"),
|
||||
common.HexToAddress("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6"),
|
||||
common.HexToAddress("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2"),
|
||||
common.HexToAddress("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a"),
|
||||
common.HexToAddress("0xd343b217de44030afaa275f54d31a9317c7f441e"),
|
||||
common.HexToAddress("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106"),
|
||||
common.HexToAddress("0xda2fef9e4a3230988ff17df2165440f37e8b1708"),
|
||||
common.HexToAddress("0xf4c64518ea10f995918a454158c6b61407ea345c"),
|
||||
common.HexToAddress("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97"),
|
||||
common.HexToAddress("0xbb9bc244d798123fde783fcc1c72d3bb8c189413"),
|
||||
common.HexToAddress("0x807640a13483f8ac783c557fcdf27be11ea4ac7a"),
|
||||
}
|
||||
}
|
||||
|
||||
// daoDrainListJSON is the JSON encoded list of accounts whose full balances will
|
||||
// be moved into a refund contract at the beginning of the dao-fork block.
|
||||
const daoDrainListJSON = `
|
||||
[
|
||||
{
|
||||
"address":"0xd4fe7bc31cedb7bfb8a345f31e668033056b2728",
|
||||
"balance":"186cc8bfaefb7be",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425"
|
||||
},
|
||||
{
|
||||
"address":"0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f",
|
||||
"balance":"b14e8feab1ff435",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xecd135fa4f61a655311e86238c92adcd779555d2"
|
||||
},
|
||||
{
|
||||
"address":"0x1975bd06d486162d5dc297798dfc41edd5d160a7",
|
||||
"balance":"359d26614cb5070c77",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6"
|
||||
},
|
||||
{
|
||||
"address":"0x319f70bab6845585f412ec7724b744fec6095c85",
|
||||
"balance":"6e075cd846d2cb1d42",
|
||||
"extraBalance":"13d34fd41b545b81",
|
||||
"extraBalanceAccount":"0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936"
|
||||
},
|
||||
{
|
||||
"address":"0x5c8536898fbb74fc7445814902fd08422eac56d0",
|
||||
"balance":"b1e5593558008fd78",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x6966ab0d485353095148a2155858910e0965b6f9"
|
||||
},
|
||||
{
|
||||
"address":"0x779543a0491a837ca36ce8c635d6154e3c4911a6",
|
||||
"balance":"392eaa20d1aad59a4c",
|
||||
"extraBalance":"426938826a96c9",
|
||||
"extraBalanceAccount":"0x2a5ed960395e2a49b1c758cef4aa15213cfd874c"
|
||||
},
|
||||
{
|
||||
"address":"0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5",
|
||||
"balance":"2875d22b29793d4ba7",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x9c50426be05db97f5d64fc54bf89eff947f0a321"
|
||||
},
|
||||
{
|
||||
"address":"0x200450f06520bdd6c527622a273333384d870efb",
|
||||
"balance":"43c341d9f96954c049",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xbe8539bfe837b67d1282b2b1d61c3f723966f049"
|
||||
},
|
||||
{
|
||||
"address":"0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb",
|
||||
"balance":"75251057154d70fa816",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xf1385fb24aad0cd7432824085e42aff90886fef5"
|
||||
},
|
||||
{
|
||||
"address":"0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091",
|
||||
"balance":"392409769296cf67f36",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd"
|
||||
},
|
||||
{
|
||||
"address":"0x51e0ddd9998364a2eb38588679f0d2c42653e4a6",
|
||||
"balance":"8ac72eccbf4e8083",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x627a0a960c079c21c34f7612d5d230e01b4ad4c7"
|
||||
},
|
||||
{
|
||||
"address":"0xf0b1aa0eb660754448a7937c022e30aa692fe0c5",
|
||||
"balance":"82289c3bb3e8c98799",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x24c4d950dfd4dd1902bbed3508144a54542bba94"
|
||||
},
|
||||
{
|
||||
"address":"0x9f27daea7aca0aa0446220b98d028715e3bc803d",
|
||||
"balance":"56bc29049ebed40fd",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90"
|
||||
},
|
||||
{
|
||||
"address":"0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b",
|
||||
"balance":"56bc7d3ff79110524",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x63ed5a272de2f6d968408b4acb9024f4cc208ebf"
|
||||
},
|
||||
{
|
||||
"address":"0x6f6704e5a10332af6672e50b3d9754dc460dfa4d",
|
||||
"balance":"23b651bd48cbc70cc",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6"
|
||||
},
|
||||
{
|
||||
"address":"0x492ea3bb0f3315521c31f273e565b868fc090f17",
|
||||
"balance":"13ea6d4fee651dd7c9",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00"
|
||||
},
|
||||
{
|
||||
"address":"0x9ea779f907f0b315b364b0cfc39a0fde5b02a416",
|
||||
"balance":"35ac471a3836ae7de5a",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xceaeb481747ca6c540a000c1f3641f8cef161fa7"
|
||||
},
|
||||
{
|
||||
"address":"0xcc34673c6c40e791051898567a1222daf90be287",
|
||||
"balance":"d529c0b76b7aa0",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x579a80d909f346fbfb1189493f521d7f48d52238"
|
||||
},
|
||||
{
|
||||
"address":"0xe308bd1ac5fda103967359b2712dd89deffb7973",
|
||||
"balance":"5cd9e7df3a8e5cdd3",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c"
|
||||
},
|
||||
{
|
||||
"address":"0xac1ecab32727358dba8962a0f3b261731aad9723",
|
||||
"balance":"2c8442fe35363313b93",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x4fd6ace747f06ece9c49699c7cabc62d02211f75"
|
||||
},
|
||||
{
|
||||
"address":"0x440c59b325d2997a134c2c7c60a8c61611212bad",
|
||||
"balance":"e77583a3958130e53",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x4486a3d68fac6967006d7a517b889fd3f98c102b"
|
||||
},
|
||||
{
|
||||
"address":"0x9c15b54878ba618f494b38f0ae7443db6af648ba",
|
||||
"balance":"1f0b6ade348ca998",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x27b137a85656544b1ccb5a0f2e561a5703c6a68f"
|
||||
},
|
||||
{
|
||||
"address":"0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241",
|
||||
"balance":"61725880736659",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x23b75c2f6791eef49c69684db4c6c1f93bf49a50"
|
||||
},
|
||||
{
|
||||
"address":"0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b",
|
||||
"balance":"42948d8dc7ddbc22d",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xb9637156d330c0d605a791f1c31ba5890582fe1c"
|
||||
},
|
||||
{
|
||||
"address":"0x6131c42fa982e56929107413a9d526fd99405560",
|
||||
"balance":"7306683851d1eafbfa",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x1591fc0f688c81fbeb17f5426a162a7024d430c2"
|
||||
},
|
||||
{
|
||||
"address":"0x542a9515200d14b68e934e9830d91645a980dd7a",
|
||||
"balance":"2a8457d0d8432e21d0c",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xc4bbd073882dd2add2424cf47d35213405b01324"
|
||||
},
|
||||
{
|
||||
"address":"0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4",
|
||||
"balance":"d8d7391feaeaa8cdb",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb"
|
||||
},
|
||||
{
|
||||
"address":"0x3ba4d81db016dc2890c81f3acec2454bff5aada5",
|
||||
"balance":"1",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab"
|
||||
},
|
||||
{
|
||||
"address":"0xe4ae1efdfc53b73893af49113d8694a057b9c0d1",
|
||||
"balance":"456397665fa74041",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5"
|
||||
},
|
||||
{
|
||||
"address":"0x0737a6b837f97f46ebade41b9bc3e1c509c85c53",
|
||||
"balance":"6324dcb7126ecbef",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x97f43a37f595ab5dd318fb46e7a155eae057317a"
|
||||
},
|
||||
{
|
||||
"address":"0x52c5317c848ba20c7504cb2c8052abd1fde29d03",
|
||||
"balance":"6c3419b0705c01cd0d",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x4863226780fe7c0356454236d3b1c8792785748d"
|
||||
},
|
||||
{
|
||||
"address":"0x5d2b2e6fcbe3b11d26b525e085ff818dae332479",
|
||||
"balance":"456397665fa74041",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c"
|
||||
},
|
||||
{
|
||||
"address":"0x057b56736d32b86616a10f619859c6cd6f59092a",
|
||||
"balance":"232c025bb44b46",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x9aa008f65de0b923a2a4f02012ad034a5e2e2192"
|
||||
},
|
||||
{
|
||||
"address":"0x304a554a310c7e546dfe434669c62820b7d83490",
|
||||
"balance":"3034f5ca7d45e17df199b",
|
||||
"extraBalance":"f7d15162c44e97b6e",
|
||||
"extraBalanceAccount":"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79"
|
||||
},
|
||||
{
|
||||
"address":"0x4deb0033bb26bc534b197e61d19e0733e5679784",
|
||||
"balance":"4417e96ed796591e09",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a"
|
||||
},
|
||||
{
|
||||
"address":"0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b",
|
||||
"balance":"d3ff7771412bbcc9",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x4fa802324e929786dbda3b8820dc7834e9134a2a"
|
||||
},
|
||||
{
|
||||
"address":"0x9da397b9e80755301a3b32173283a91c0ef6c87e",
|
||||
"balance":"32ae324c233816b4c2",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6"
|
||||
},
|
||||
{
|
||||
"address":"0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9",
|
||||
"balance":"1e530695b705f037c6",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x5dc28b15dffed94048d73806ce4b7a4612a1d48f"
|
||||
},
|
||||
{
|
||||
"address":"0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76",
|
||||
"balance":"68013bad5b4b1133fc5",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x12e626b0eebfe86a56d633b9864e389b45dcb260"
|
||||
},
|
||||
{
|
||||
"address":"0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7",
|
||||
"balance":"456397665fa74041",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5"
|
||||
},
|
||||
{
|
||||
"address":"0xd164b088bd9108b60d0ca3751da4bceb207b0782",
|
||||
"balance":"3635ce47fabaaa336e",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x6231b6d0d5e77fe001c2a460bd9584fee60d409b"
|
||||
},
|
||||
{
|
||||
"address":"0x1cba23d343a983e9b5cfd19496b9a9701ada385f",
|
||||
"balance":"f3abd9906c170a",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xa82f360a8d3455c5c41366975bde739c37bfeb8a"
|
||||
},
|
||||
{
|
||||
"address":"0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339",
|
||||
"balance":"4c6679d9d9b95a4e08",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x005f5cee7a43331d5a3d3eec71305925a62f34b6"
|
||||
},
|
||||
{
|
||||
"address":"0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d",
|
||||
"balance":"40f622936475de31849",
|
||||
"extraBalance":"671e1bbabded39754",
|
||||
"extraBalanceAccount":"0xd131637d5275fd1a68a3200f4ad25c71a2a9522e"
|
||||
},
|
||||
{
|
||||
"address":"0xbc07118b9ac290e4622f5e77a0853539789effbe",
|
||||
"balance":"1316ccfa4a35db5e58f",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x47e7aa56d6bdf3f36be34619660de61275420af8"
|
||||
},
|
||||
{
|
||||
"address":"0xacd87e28b0c9d1254e868b81cba4cc20d9a32225",
|
||||
"balance":"b3ad6bb72000bab9f",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xadf80daec7ba8dcf15392f1ac611fff65d94f880"
|
||||
},
|
||||
{
|
||||
"address":"0x5524c55fb03cf21f549444ccbecb664d0acad706",
|
||||
"balance":"16f2da372a5c8a70967",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x40b803a9abce16f50f36a77ba41180eb90023925"
|
||||
},
|
||||
{
|
||||
"address":"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
|
||||
"balance":"ea0b1bdc78f500a43",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x17802f43a0137c506ba92291391a8a8f207f487d"
|
||||
},
|
||||
{
|
||||
"address":"0x253488078a4edf4d6f42f113d1e62836a942cf1a",
|
||||
"balance":"3060e3aed135cc80",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915"
|
||||
},
|
||||
{
|
||||
"address":"0xb136707642a4ea12fb4bae820f03d2562ebff487",
|
||||
"balance":"6050bdeb3354b5c98adc3",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940"
|
||||
},
|
||||
{
|
||||
"address":"0xf14c14075d6c4ed84b86798af0956deef67365b5",
|
||||
"balance":"1d77844e94c25ba2",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xca544e5c4687d109611d0f8f928b53a25af72448"
|
||||
},
|
||||
{
|
||||
"address":"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
|
||||
"balance":"2e93a72de4fc5ec0ed",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7"
|
||||
},
|
||||
{
|
||||
"address":"0x6d87578288b6cb5549d5076a207456a1f6a63dc0",
|
||||
"balance":"1afd340799e48c18",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e"
|
||||
},
|
||||
{
|
||||
"address":"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
|
||||
"balance":"14d0944eb3be947a8",
|
||||
"extraBalance":"0",
|
||||
"extraBalanceAccount":"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2"
|
||||
},
|
||||
{
|
||||
"address":"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
|
||||
"balance":"6202b236a200e365eba",
|
||||
"extraBalance":"11979be9020f03ec4ec",
|
||||
"extraBalanceAccount":"0xd343b217de44030afaa275f54d31a9317c7f441e"
|
||||
},
|
||||
{
|
||||
"address":"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
|
||||
"balance":"7ed634ebbba531901e07",
|
||||
"extraBalance":"f9c5eff28cb08720c85",
|
||||
"extraBalanceAccount":"0xda2fef9e4a3230988ff17df2165440f37e8b1708"
|
||||
},
|
||||
{
|
||||
"address":"0xf4c64518ea10f995918a454158c6b61407ea345c",
|
||||
"balance":"39152e15508a96ff894a",
|
||||
"extraBalance":"14041ca908bcc185c8",
|
||||
"extraBalanceAccount":"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97"
|
||||
},
|
||||
{
|
||||
"address":"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
|
||||
"balance":"1",
|
||||
"extraBalance":"5553ebc",
|
||||
"extraBalanceAccount":"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
|
||||
}
|
||||
]
|
||||
`
|
||||
|
Loading…
Reference in New Issue
Block a user