forked from cerc-io/plugeth
core: refactor genesis handling
This commit solves several issues concerning the genesis block: * Genesis/ChainConfig loading was handled by cmd/geth code. This left library users in the cold. They could specify a JSON-encoded string and overwrite the config, but didn't get any of the additional checks performed by geth. * Decoding and writing of genesis JSON was conflated in WriteGenesisBlock. This made it a lot harder to embed the genesis block into the forthcoming config file loader. This commit changes things so there is a single Genesis type that represents genesis blocks. All uses of Write*Genesis* are changed to use the new type instead. * If the chain config supplied by the user was incompatible with the current chain (i.e. the chain had already advanced beyond a scheduled fork), it got overwritten. This is not an issue in practice because previous forks have always had the highest total difficulty. It might matter in the future though. The new code reverts the local chain to the point of the fork when upgrading configuration. The change to genesis block data removes compression library dependencies from package core.
This commit is contained in:
parent
67c47459f2
commit
37dd9086ec
@ -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
|
||||
}
|
||||
|
@ -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 testGenesis(account common.Address, balance *big.Int) *Genesis {
|
||||
return &Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Alloc: GenesisAlloc{account: {Balance: balance}},
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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())
|
||||
// newTestBlockChain creates a blockchain without validation.
|
||||
func newTestBlockChain() *BlockChain {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
gspec := &Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Difficulty: big.NewInt(1),
|
||||
}
|
||||
|
||||
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{})
|
||||
gspec.MustCommit(db)
|
||||
blockchain, err := NewBlockChain(db, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
|
||||
if err != nil {
|
||||
t.Error("failed creating blockchain:", err)
|
||||
t.FailNow()
|
||||
return 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
|
||||
}
|
390
core/genesis.go
390
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(contents, &genesis); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if genesis.ChainConfig == nil {
|
||||
genesis.ChainConfig = 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))
|
||||
}
|
@ -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)
|
||||
|
@ -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())
|
||||
// newTestLightChain creates a LightChain that doesn't validate anything.
|
||||
func newTestLightChain() *LightChain {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
gspec := &core.Genesis{
|
||||
Difficulty: big.NewInt(1),
|
||||
Config: testChainConfig(),
|
||||
}
|
||||
|
||||
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)
|
||||
gspec.MustCommit(db)
|
||||
lc, err := NewLightChain(&dummyOdr{db: db}, gspec.Config, pow.NewTestEthash(), new(event.TypeMux))
|
||||
if err != nil {
|
||||
t.Error("failed creating LightChain:", err)
|
||||
t.FailNow()
|
||||
return nil
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return LightChain
|
||||
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.
|
||||
|
154
params/config.go
154
params/config.go
@ -23,8 +23,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
var (
|
||||
// MainnetChainConfig is the chain parameters to run a node on the main network.
|
||||
var MainnetChainConfig = &ChainConfig{
|
||||
MainnetChainConfig = &ChainConfig{
|
||||
ChainId: MainNetChainID,
|
||||
HomesteadBlock: MainNetHomesteadBlock,
|
||||
DAOForkBlock: MainNetDAOForkBlock,
|
||||
@ -35,8 +36,8 @@ var MainnetChainConfig = &ChainConfig{
|
||||
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,
|
||||
@ -49,13 +50,16 @@ var TestnetChainConfig = &ChainConfig{
|
||||
|
||||
// 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.
|
||||
var AllProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0)}
|
||||
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 isForked(c.HomesteadBlock, num)
|
||||
}
|
||||
return num.Cmp(c.HomesteadBlock) >= 0
|
||||
|
||||
// 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
|
||||
|
||||
if y == nil {
|
||||
return x == nil
|
||||
}
|
||||
return x.Cmp(y) == 0
|
||||
}
|
||||
|
||||
func (c *ChainConfig) IsEIP158(num *big.Int) bool {
|
||||
if c.EIP158Block == nil || num == nil {
|
||||
return false
|
||||
}
|
||||
return num.Cmp(c.EIP158Block) >= 0
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
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 (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 (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