From f0cbebb19f3137ee3ba0e66dadd1b5b9dbf98b1c Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Tue, 1 Mar 2016 23:32:43 +0100 Subject: core: added basic chain configuration Added chain configuration options and write out during genesis database insertion. If no "config" was found, nothing is written to the database. Configurations are written on a per genesis base. This means that any chain (which is identified by it's genesis hash) can have their own chain settings. --- eth/api.go | 24 ++++++++++++++---------- eth/backend.go | 42 +++++++++++++++++++++++++++++++----------- eth/handler.go | 4 ++-- eth/helper_test.go | 7 +++++-- 4 files changed, 52 insertions(+), 25 deletions(-) (limited to 'eth') diff --git a/eth/api.go b/eth/api.go index 4a03a0940..06c10daa9 100644 --- a/eth/api.go +++ b/eth/api.go @@ -456,6 +456,7 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool { // PublicBlockChainAPI provides an API to access the Ethereum blockchain. // It offers only methods that operate on public data that is freely available to anyone. type PublicBlockChainAPI struct { + config *core.ChainConfig bc *core.BlockChain chainDb ethdb.Database eventMux *event.TypeMux @@ -464,8 +465,8 @@ type PublicBlockChainAPI struct { } // NewPublicBlockChainAPI creates a new Etheruem blockchain API. -func NewPublicBlockChainAPI(bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI { - return &PublicBlockChainAPI{bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am} +func NewPublicBlockChainAPI(config *core.ChainConfig, bc *core.BlockChain, m *miner.Miner, chainDb ethdb.Database, eventMux *event.TypeMux, am *accounts.Manager) *PublicBlockChainAPI { + return &PublicBlockChainAPI{config: config, bc: bc, miner: m, chainDb: chainDb, eventMux: eventMux, am: am} } // BlockNumber returns the block number of the chain head. @@ -670,7 +671,7 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st } // Execute the call and return - vmenv := core.NewEnv(stateDb, s.bc, msg, block.Header(), nil) + vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), s.config.VmConfig) gp := new(core.GasPool).AddGas(common.MaxBig) res, gas, err := core.ApplyMessage(vmenv, msg, gp) @@ -1501,13 +1502,14 @@ func (api *PublicDebugAPI) SeedHash(number uint64) (string, error) { // PrivateDebugAPI is the collection of Etheruem APIs exposed over the private // debugging endpoint. type PrivateDebugAPI struct { - eth *Ethereum + config *core.ChainConfig + eth *Ethereum } // NewPrivateDebugAPI creates a new API definition for the private debug methods // of the Ethereum service. -func NewPrivateDebugAPI(eth *Ethereum) *PrivateDebugAPI { - return &PrivateDebugAPI{eth: eth} +func NewPrivateDebugAPI(config *core.ChainConfig, eth *Ethereum) *PrivateDebugAPI { + return &PrivateDebugAPI{config: config, eth: eth} } // BlockTraceResults is the returned value when replaying a block to check for @@ -1601,7 +1603,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config vm.Config) (bo config.Debug = true // make sure debug is set. config.Logger.Collector = collector - if err := core.ValidateHeader(blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil { + if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil { return false, collector.traces, err } statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), api.eth.ChainDb()) @@ -1609,7 +1611,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, config vm.Config) (bo return false, collector.traces, err } - receipts, _, usedGas, err := processor.Process(block, statedb, &config) + receipts, _, usedGas, err := processor.Process(block, statedb, config) if err != nil { return false, collector.traces, err } @@ -1731,7 +1733,7 @@ func (s *PrivateDebugAPI) TraceTransaction(txHash common.Hash, logger vm.LogConf data: tx.Data(), } - vmenv := core.NewEnv(stateDb, s.eth.BlockChain(), msg, block.Header(), &vm.Config{ + vmenv := core.NewEnv(stateDb, s.config, s.eth.BlockChain(), msg, block.Header(), vm.Config{ Debug: true, Logger: logger, }) @@ -1788,7 +1790,9 @@ func (s *PublicBlockChainAPI) TraceCall(args CallArgs, blockNr rpc.BlockNumber) } // Execute the call and return - vmenv := core.NewEnv(stateDb, s.bc, msg, block.Header(), nil) + vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), vm.Config{ + Debug: true, + }) gp := new(core.GasPool).AddGas(common.MaxBig) ret, gas, err := core.ApplyMessage(vmenv, msg, gp) diff --git a/eth/backend.go b/eth/backend.go index 4f3e11a50..3c3440a53 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -63,6 +63,8 @@ var ( ) type Config struct { + ChainConfig *core.ChainConfig // chain configuration + 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 @@ -100,6 +102,7 @@ type Config struct { } type Ethereum struct { + chainConfig *core.ChainConfig // Channel for shutting down the ethereum shutdownChan chan bool @@ -166,12 +169,17 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { // Load up any custom genesis block if requested if len(config.Genesis) > 0 { + // Using println instead of glog to make sure it **always** displays regardless of + // verbosity settings. + common.PrintDepricationWarning("--genesis is deprecated. Switch to use 'geth init /path/to/file'") + block, err := core.WriteGenesisBlock(chainDb, strings.NewReader(config.Genesis)) if err != nil { return nil, err } glog.V(logger.Info).Infof("Successfully wrote custom genesis block: %x", block.Hash()) } + // Load up a test setup if directly injected if config.TestGenesisState != nil { chainDb = config.TestGenesisState @@ -227,26 +235,38 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { default: eth.pow = ethash.New() } - //genesis := core.GenesisBlock(uint64(config.GenesisNonce), stateDb) - eth.blockchain, err = core.NewBlockChain(chainDb, eth.pow, eth.EventMux()) - eth.blockchain.SetConfig(&vm.Config{ + + // 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)) + if genesis == nil { + genesis, err = core.WriteDefaultGenesisBlock(chainDb) + if err != nil { + return nil, err + } + glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block") + } + + eth.chainConfig = config.ChainConfig + eth.chainConfig.VmConfig = vm.Config{ EnableJit: config.EnableJit, ForceJit: config.ForceJit, - }) + } + eth.blockchain, err = core.NewBlockChain(chainDb, 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, fmt.Errorf(`No chain found. Please initialise a new chain using the "init" subcommand.`) } return nil, err } - newPool := core.NewTxPool(eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit) + newPool := core.NewTxPool(eth.chainConfig, eth.EventMux(), eth.blockchain.State, eth.blockchain.GasLimit) eth.txPool = newPool - if eth.protocolManager, err = NewProtocolManager(config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil { + if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil { return nil, err } - eth.miner = miner.New(eth, eth.EventMux(), eth.pow) + eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow) eth.miner.SetGasPrice(config.GasPrice) eth.miner.SetExtra(config.ExtraData) @@ -275,7 +295,7 @@ func (s *Ethereum) APIs() []rpc.API { }, { Namespace: "eth", Version: "1.0", - Service: NewPublicBlockChainAPI(s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()), + Service: NewPublicBlockChainAPI(s.chainConfig, s.BlockChain(), s.Miner(), s.ChainDb(), s.EventMux(), s.AccountManager()), Public: true, }, { Namespace: "eth", @@ -319,7 +339,7 @@ func (s *Ethereum) APIs() []rpc.API { }, { Namespace: "debug", Version: "1.0", - Service: NewPrivateDebugAPI(s), + Service: NewPrivateDebugAPI(s.chainConfig, s), }, { Namespace: "net", Version: "1.0", @@ -328,7 +348,7 @@ func (s *Ethereum) APIs() []rpc.API { }, { Namespace: "admin", Version: "1.0", - Service: ethreg.NewPrivateRegistarAPI(s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()), + Service: ethreg.NewPrivateRegistarAPI(s.chainConfig, s.BlockChain(), s.ChainDb(), s.TxPool(), s.AccountManager()), }, } } diff --git a/eth/handler.go b/eth/handler.go index 2c5cae479..135de3749 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -86,7 +86,7 @@ type ProtocolManager struct { // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // with the ethereum network. -func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { +func NewProtocolManager(config *core.ChainConfig, fastSync bool, networkId int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { // Figure out whether to allow fast sync or not if fastSync && blockchain.CurrentBlock().NumberU64() > 0 { glog.V(logger.Info).Infof("blockchain not empty, fast sync disabled") @@ -144,7 +144,7 @@ func NewProtocolManager(fastSync bool, networkId int, mux *event.TypeMux, txpool manager.removePeer) validator := func(block *types.Block, parent *types.Block) error { - return core.ValidateHeader(pow, block.Header(), parent.Header(), true, false) + return core.ValidateHeader(config, pow, block.Header(), parent.Header(), true, false) } heighter := func() uint64 { return blockchain.CurrentBlock().NumberU64() diff --git a/eth/helper_test.go b/eth/helper_test.go index bbd1fb818..5d141ce56 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -17,6 +17,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" + "github.com/ethereum/go-ethereum/params" ) var ( @@ -34,13 +35,15 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core pow = new(core.FakePow) db, _ = ethdb.NewMemDatabase() genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{testBankAddress, testBankFunds}) - blockchain, _ = core.NewBlockChain(db, pow, evmux) + chainConfig = &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock} + blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux) ) chain, _ := core.GenerateChain(genesis, db, blocks, generator) if _, err := blockchain.InsertChain(chain); err != nil { panic(err) } - pm, err := NewProtocolManager(fastSync, NetworkId, evmux, &testTxPool{added: newtx}, pow, blockchain, db) + + pm, err := NewProtocolManager(chainConfig, fastSync, NetworkId, evmux, &testTxPool{added: newtx}, pow, blockchain, db) if err != nil { return nil, err } -- cgit v1.2.3 From 9055c16efad80d0c69992e7992083f967733aa9c Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Thu, 31 Mar 2016 17:43:41 +0200 Subject: accounts/a/b/backends, core: chain maker homestead block set to 0 The chain maker and the simulated backend now run with a homestead phase beginning at block 0 (i.e. there's no frontier). This commit also fixes up #2388 --- eth/helper_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'eth') diff --git a/eth/helper_test.go b/eth/helper_test.go index 5d141ce56..13de18670 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -17,7 +17,6 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" - "github.com/ethereum/go-ethereum/params" ) var ( @@ -35,7 +34,7 @@ func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core pow = new(core.FakePow) db, _ = ethdb.NewMemDatabase() genesis = core.WriteGenesisBlockForTesting(db, core.GenesisAccount{testBankAddress, testBankFunds}) - chainConfig = &core.ChainConfig{HomesteadBlock: params.MainNetHomesteadBlock} + chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)} // homestead set to 0 because of chain maker blockchain, _ = core.NewBlockChain(db, chainConfig, pow, evmux) ) chain, _ := core.GenerateChain(genesis, db, blocks, generator) -- cgit v1.2.3 From 1f3596c25af077a3303c554ee6b49404b20f7117 Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Fri, 1 Apr 2016 00:30:21 +0200 Subject: core: transition db now also returns the required gas amount Exposes some core methods to transition and compute new state information and adds an additional return value to the transition db method to fetch required gas for that particular message (excluding gas refunds from any SSTORE[X] = 0 and SUICIDE. Fixes #2395 --- eth/api.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'eth') diff --git a/eth/api.go b/eth/api.go index 06c10daa9..af03c096d 100644 --- a/eth/api.go +++ b/eth/api.go @@ -674,11 +674,11 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st vmenv := core.NewEnv(stateDb, s.config, s.bc, msg, block.Header(), s.config.VmConfig) gp := new(core.GasPool).AddGas(common.MaxBig) - res, gas, err := core.ApplyMessage(vmenv, msg, gp) + res, requiredGas, _, err := core.NewStateTransition(vmenv, msg, gp).TransitionDb() if len(res) == 0 { // backwards compatibility - return "0x", gas, err + return "0x", requiredGas, err } - return common.ToHex(res), gas, err + return common.ToHex(res), requiredGas, err } // Call executes the given transaction on the state for the given block number. -- cgit v1.2.3