Skip to content

Commit 37dd908

Browse files
committed
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.
1 parent 67c4745 commit 37dd908

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1371
-1267
lines changed

accounts/abi/bind/backends/simulated.go

+8-10
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ import (
3737
"github.com/ethereum/go-ethereum/pow"
3838
)
3939

40-
// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
41-
var chainConfig = &params.ChainConfig{HomesteadBlock: big.NewInt(0), EIP150Block: new(big.Int), EIP158Block: new(big.Int)}
42-
4340
// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
4441
var _ bind.ContractBackend = (*SimulatedBackend)(nil)
4542

@@ -60,11 +57,12 @@ type SimulatedBackend struct {
6057

6158
// NewSimulatedBackend creates a new binding backend using a simulated blockchain
6259
// for testing purposes.
63-
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
60+
func NewSimulatedBackend(alloc core.GenesisAlloc) *SimulatedBackend {
6461
database, _ := ethdb.NewMemDatabase()
65-
core.WriteGenesisBlockForTesting(database, accounts...)
66-
blockchain, _ := core.NewBlockChain(database, chainConfig, new(pow.FakePow), new(event.TypeMux), vm.Config{})
67-
backend := &SimulatedBackend{database: database, blockchain: blockchain}
62+
genesis := core.Genesis{Config: params.AllProtocolChanges, Alloc: alloc}
63+
genesis.MustCommit(database)
64+
blockchain, _ := core.NewBlockChain(database, genesis.Config, new(pow.FakePow), new(event.TypeMux), vm.Config{})
65+
backend := &SimulatedBackend{database: database, blockchain: blockchain, config: genesis.Config}
6866
backend.rollback()
6967
return backend
7068
}
@@ -90,7 +88,7 @@ func (b *SimulatedBackend) Rollback() {
9088
}
9189

9290
func (b *SimulatedBackend) rollback() {
93-
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
91+
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})
9492
b.pendingBlock = blocks[0]
9593
b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
9694
}
@@ -253,7 +251,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
253251
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain)
254252
// Create a new environment which holds all relevant information
255253
// about the transaction and calling mechanisms.
256-
vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{})
254+
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
257255
gaspool := new(core.GasPool).AddGas(math.MaxBig256)
258256
ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
259257
return ret, gasUsed, err
@@ -274,7 +272,7 @@ func (b *SimulatedBackend) SendTransaction(ctx context.Context, tx *types.Transa
274272
panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
275273
}
276274

277-
blocks, _ := core.GenerateChain(chainConfig, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
275+
blocks, _ := core.GenerateChain(b.config, b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
278276
for _, tx := range b.pendingBlock.Transactions() {
279277
block.AddTx(tx)
280278
}

accounts/abi/bind/bind_test.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ var bindTests = []struct {
169169
// Generate a new random account and a funded simulator
170170
key, _ := crypto.GenerateKey()
171171
auth := bind.NewKeyedTransactor(key)
172-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
172+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
173173
174174
// Deploy an interaction tester contract and call a transaction on it
175175
_, _, interactor, err := DeployInteractor(auth, sim, "Deploy string")
@@ -210,7 +210,7 @@ var bindTests = []struct {
210210
// Generate a new random account and a funded simulator
211211
key, _ := crypto.GenerateKey()
212212
auth := bind.NewKeyedTransactor(key)
213-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
213+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
214214
215215
// Deploy a tuple tester contract and execute a structured call on it
216216
_, _, getter, err := DeployGetter(auth, sim)
@@ -242,7 +242,7 @@ var bindTests = []struct {
242242
// Generate a new random account and a funded simulator
243243
key, _ := crypto.GenerateKey()
244244
auth := bind.NewKeyedTransactor(key)
245-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
245+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
246246
247247
// Deploy a tuple tester contract and execute a structured call on it
248248
_, _, tupler, err := DeployTupler(auth, sim)
@@ -284,7 +284,7 @@ var bindTests = []struct {
284284
// Generate a new random account and a funded simulator
285285
key, _ := crypto.GenerateKey()
286286
auth := bind.NewKeyedTransactor(key)
287-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
287+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
288288
289289
// Deploy a slice tester contract and execute a n array call on it
290290
_, _, slicer, err := DeploySlicer(auth, sim)
@@ -318,7 +318,7 @@ var bindTests = []struct {
318318
// Generate a new random account and a funded simulator
319319
key, _ := crypto.GenerateKey()
320320
auth := bind.NewKeyedTransactor(key)
321-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
321+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
322322
323323
// Deploy a default method invoker contract and execute its default method
324324
_, _, defaulter, err := DeployDefaulter(auth, sim)
@@ -351,7 +351,7 @@ var bindTests = []struct {
351351
`[{"constant":true,"inputs":[],"name":"String","outputs":[{"name":"","type":"string"}],"type":"function"}]`,
352352
`
353353
// Create a simulator and wrap a non-deployed contract
354-
sim := backends.NewSimulatedBackend()
354+
sim := backends.NewSimulatedBackend(nil)
355355
356356
nonexistent, err := NewNonExistent(common.Address{}, sim)
357357
if err != nil {
@@ -387,7 +387,7 @@ var bindTests = []struct {
387387
// Generate a new random account and a funded simulator
388388
key, _ := crypto.GenerateKey()
389389
auth := bind.NewKeyedTransactor(key)
390-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
390+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
391391
392392
// Deploy a funky gas pattern contract
393393
_, _, limiter, err := DeployFunkyGasPattern(auth, sim)
@@ -423,7 +423,7 @@ var bindTests = []struct {
423423
// Generate a new random account and a funded simulator
424424
key, _ := crypto.GenerateKey()
425425
auth := bind.NewKeyedTransactor(key)
426-
sim := backends.NewSimulatedBackend(core.GenesisAccount{Address: auth.From, Balance: big.NewInt(10000000000)})
426+
sim := backends.NewSimulatedBackend(core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}})
427427
428428
// Deploy a sender tester contract and execute a structured call on it
429429
_, _, callfrom, err := DeployCallFrom(auth, sim)
@@ -458,7 +458,7 @@ func TestBindings(t *testing.T) {
458458
t.Skip("go sdk not found for testing")
459459
}
460460
// Skip the test if the go-ethereum sources are symlinked (https://github.com/golang/go/issues/14845)
461-
linkTestCode := fmt.Sprintf("package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend())\n}")
461+
linkTestCode := fmt.Sprintf("package linktest\nfunc CheckSymlinks(){\nfmt.Println(backends.NewSimulatedBackend(nil))\n}")
462462
linkTestDeps, err := imports.Process("", []byte(linkTestCode), nil)
463463
if err != nil {
464464
t.Fatalf("failed check for goimports symlink bug: %v", err)

accounts/abi/bind/util_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ var waitDeployedTests = map[string]struct {
5353

5454
func TestWaitDeployed(t *testing.T) {
5555
for name, test := range waitDeployedTests {
56-
backend := backends.NewSimulatedBackend(core.GenesisAccount{
57-
Address: crypto.PubkeyToAddress(testKey.PublicKey),
58-
Balance: big.NewInt(10000000000),
56+
backend := backends.NewSimulatedBackend(core.GenesisAlloc{
57+
crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(10000000000)},
5958
})
6059

6160
// Create the transaction.

cmd/geth/chaincmd.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package main
1818

1919
import (
20+
"encoding/json"
2021
"fmt"
2122
"os"
2223
"runtime"
@@ -110,17 +111,22 @@ func initGenesis(ctx *cli.Context) error {
110111
stack := makeFullNode(ctx)
111112
chaindb := utils.MakeChainDatabase(ctx, stack)
112113

113-
genesisFile, err := os.Open(genesisPath)
114+
file, err := os.Open(genesisPath)
114115
if err != nil {
115116
utils.Fatalf("failed to read genesis file: %v", err)
116117
}
117-
defer genesisFile.Close()
118+
defer file.Close()
118119

119-
block, err := core.WriteGenesisBlock(chaindb, genesisFile)
120+
genesis := new(core.Genesis)
121+
if err := json.NewDecoder(file).Decode(genesis); err != nil {
122+
utils.Fatalf("invalid genesis file: %v", err)
123+
}
124+
125+
_, hash, err := core.SetupGenesisBlock(chaindb, genesis)
120126
if err != nil {
121127
utils.Fatalf("failed to write genesis block: %v", err)
122128
}
123-
log.Info("Successfully wrote genesis state", "hash", block.Hash())
129+
log.Info("Successfully wrote genesis state", "hash", hash)
124130
return nil
125131
}
126132

cmd/utils/flags.go

+18-73
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
786786

787787
ethConf := &eth.Config{
788788
Etherbase: MakeEtherbase(ks, ctx),
789-
ChainConfig: MakeChainConfig(ctx, stack),
790789
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
791790
LightMode: ctx.GlobalBool(LightModeFlag.Name),
792791
LightServ: ctx.GlobalInt(LightServFlag.Name),
@@ -822,7 +821,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
822821
ethConf.NetworkId = 3
823822
}
824823
ethConf.Genesis = core.DefaultTestnetGenesisBlock()
825-
826824
case ctx.GlobalBool(DevModeFlag.Name):
827825
ethConf.Genesis = core.DevGenesisBlock()
828826
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
@@ -884,67 +882,6 @@ func SetupNetwork(ctx *cli.Context) {
884882
params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name))
885883
}
886884

887-
// MakeChainConfig reads the chain configuration from the database in ctx.Datadir.
888-
func MakeChainConfig(ctx *cli.Context, stack *node.Node) *params.ChainConfig {
889-
db := MakeChainDatabase(ctx, stack)
890-
defer db.Close()
891-
892-
return MakeChainConfigFromDb(ctx, db)
893-
}
894-
895-
// MakeChainConfigFromDb reads the chain configuration from the given database.
896-
func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *params.ChainConfig {
897-
// If the chain is already initialized, use any existing chain configs
898-
config := new(params.ChainConfig)
899-
900-
genesis := core.GetBlock(db, core.GetCanonicalHash(db, 0), 0)
901-
if genesis != nil {
902-
storedConfig, err := core.GetChainConfig(db, genesis.Hash())
903-
switch err {
904-
case nil:
905-
config = storedConfig
906-
case core.ChainConfigNotFoundErr:
907-
// No configs found, use empty, will populate below
908-
default:
909-
Fatalf("Could not make chain configuration: %v", err)
910-
}
911-
}
912-
// set chain id in case it's zero.
913-
if config.ChainId == nil {
914-
config.ChainId = new(big.Int)
915-
}
916-
// Check whether we are allowed to set default config params or not:
917-
// - If no genesis is set, we're running either mainnet or testnet (private nets use `geth init`)
918-
// - If a genesis is already set, ensure we have a configuration for it (mainnet or testnet)
919-
defaults := genesis == nil ||
920-
(genesis.Hash() == params.MainNetGenesisHash && !ctx.GlobalBool(TestNetFlag.Name)) ||
921-
(genesis.Hash() == params.TestNetGenesisHash && ctx.GlobalBool(TestNetFlag.Name))
922-
923-
if defaults {
924-
if ctx.GlobalBool(TestNetFlag.Name) {
925-
config = params.TestnetChainConfig
926-
} else if ctx.GlobalBool(DevModeFlag.Name) {
927-
config = params.AllProtocolChanges
928-
} else {
929-
// Homestead fork
930-
config.HomesteadBlock = params.MainNetHomesteadBlock
931-
// DAO fork
932-
config.DAOForkBlock = params.MainNetDAOForkBlock
933-
config.DAOForkSupport = true
934-
935-
// DoS reprice fork
936-
config.EIP150Block = params.MainNetHomesteadGasRepriceBlock
937-
config.EIP150Hash = params.MainNetHomesteadGasRepriceHash
938-
939-
// DoS state cleanup fork
940-
config.EIP155Block = params.MainNetSpuriousDragon
941-
config.EIP158Block = params.MainNetSpuriousDragon
942-
config.ChainId = params.MainNetChainID
943-
}
944-
}
945-
return config
946-
}
947-
948885
func ChainDbName(ctx *cli.Context) string {
949886
if ctx.GlobalBool(LightModeFlag.Name) {
950887
return "lightchaindata"
@@ -968,26 +905,34 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
968905
return chainDb
969906
}
970907

908+
func MakeGenesis(ctx *cli.Context) *core.Genesis {
909+
var genesis *core.Genesis
910+
switch {
911+
case ctx.GlobalBool(TestNetFlag.Name):
912+
genesis = core.DefaultTestnetGenesisBlock()
913+
case ctx.GlobalBool(DevModeFlag.Name):
914+
genesis = core.DevGenesisBlock()
915+
}
916+
return genesis
917+
}
918+
971919
// MakeChain creates a chain manager from set command line flags.
972920
func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
973921
var err error
974922
chainDb = MakeChainDatabase(ctx, stack)
975923

976-
if ctx.GlobalBool(TestNetFlag.Name) {
977-
_, err := core.WriteTestNetGenesisBlock(chainDb)
978-
if err != nil {
979-
Fatalf("Failed to write testnet genesis: %v", err)
980-
}
981-
}
982-
chainConfig := MakeChainConfigFromDb(ctx, chainDb)
983-
984924
seal := pow.PoW(pow.FakePow{})
985925
if !ctx.GlobalBool(FakePoWFlag.Name) {
986926
seal = pow.NewFullEthash("", 1, 0, "", 1, 0)
987927
}
988-
chain, err = core.NewBlockChain(chainDb, chainConfig, seal, new(event.TypeMux), vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)})
928+
config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
929+
if err != nil {
930+
Fatalf("%v", err)
931+
}
932+
vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
933+
chain, err = core.NewBlockChain(chainDb, config, seal, new(event.TypeMux), vmcfg)
989934
if err != nil {
990-
Fatalf("Could not start chainmanager: %v", err)
935+
Fatalf("Can't create BlockChain: %v", err)
991936
}
992937
return chain, chainDb
993938
}

console/console_test.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,16 @@ import (
2121
"errors"
2222
"fmt"
2323
"io/ioutil"
24-
"math/big"
2524
"os"
2625
"strings"
2726
"testing"
2827
"time"
2928

3029
"github.com/ethereum/go-ethereum/common"
30+
"github.com/ethereum/go-ethereum/core"
3131
"github.com/ethereum/go-ethereum/eth"
3232
"github.com/ethereum/go-ethereum/internal/jsre"
3333
"github.com/ethereum/go-ethereum/node"
34-
"github.com/ethereum/go-ethereum/params"
3534
)
3635

3736
const (
@@ -97,9 +96,9 @@ func newTester(t *testing.T, confOverride func(*eth.Config)) *tester {
9796
t.Fatalf("failed to create node: %v", err)
9897
}
9998
ethConf := &eth.Config{
100-
ChainConfig: &params.ChainConfig{HomesteadBlock: new(big.Int), ChainId: new(big.Int)},
101-
Etherbase: common.HexToAddress(testAddress),
102-
PowTest: true,
99+
Genesis: core.DevGenesisBlock(),
100+
Etherbase: common.HexToAddress(testAddress),
101+
PowTest: true,
103102
}
104103
if confOverride != nil {
105104
confOverride(ethConf)

contracts/chequebook/cheque_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ var (
4242
)
4343

4444
func newTestBackend() *backends.SimulatedBackend {
45-
return backends.NewSimulatedBackend(
46-
core.GenesisAccount{Address: addr0, Balance: big.NewInt(1000000000)},
47-
core.GenesisAccount{Address: addr1, Balance: big.NewInt(1000000000)},
48-
core.GenesisAccount{Address: addr2, Balance: big.NewInt(1000000000)},
49-
)
45+
return backends.NewSimulatedBackend(core.GenesisAlloc{
46+
addr0: {Balance: big.NewInt(1000000000)},
47+
addr1: {Balance: big.NewInt(1000000000)},
48+
addr2: {Balance: big.NewInt(1000000000)},
49+
})
5050
}
5151

5252
func deploy(prvKey *ecdsa.PrivateKey, amount *big.Int, backend *backends.SimulatedBackend) (common.Address, error) {

contracts/ens/ens_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var (
3434
)
3535

3636
func TestENS(t *testing.T) {
37-
contractBackend := backends.NewSimulatedBackend(core.GenesisAccount{Address: addr, Balance: big.NewInt(1000000000)})
37+
contractBackend := backends.NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(1000000000)}})
3838
transactOpts := bind.NewKeyedTransactor(key)
3939
// Workaround for bug estimating gas in the call to Register
4040
transactOpts.GasLimit = big.NewInt(1000000)

contracts/release/contract_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ func setupReleaseTest(t *testing.T, prefund ...*ecdsa.PrivateKey) (*ecdsa.Privat
3535
key, _ := crypto.GenerateKey()
3636
auth := bind.NewKeyedTransactor(key)
3737

38-
accounts := []core.GenesisAccount{{Address: auth.From, Balance: big.NewInt(10000000000)}}
38+
alloc := core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}
3939
for _, key := range prefund {
40-
accounts = append(accounts, core.GenesisAccount{Address: crypto.PubkeyToAddress(key.PublicKey), Balance: big.NewInt(10000000000)})
40+
alloc[crypto.PubkeyToAddress(key.PublicKey)] = core.GenesisAccount{Balance: big.NewInt(10000000000)}
4141
}
42-
sim := backends.NewSimulatedBackend(accounts...)
42+
sim := backends.NewSimulatedBackend(alloc)
4343

4444
// Deploy a version oracle contract, commit and return
4545
_, _, oracle, err := DeployReleaseOracle(auth, sim, []common.Address{auth.From})

0 commit comments

Comments
 (0)