From 09777952ee476ff80d4b6e63b5041ff5ca0e441b Mon Sep 17 00:00:00 2001 From: Péter Szilágyi Date: Wed, 5 Apr 2017 01:16:29 +0300 Subject: core, consensus: pluggable consensus engines (#3817) This commit adds pluggable consensus engines to go-ethereum. In short, it introduces a generic consensus interface, and refactors the entire codebase to use this interface. --- eth/api.go | 93 +++++++++++++++++++++++++-------------------- eth/backend.go | 49 ++++++++++++------------ eth/fetcher/fetcher.go | 12 +++--- eth/fetcher/fetcher_test.go | 6 +-- eth/handler.go | 11 +++--- eth/handler_test.go | 4 +- eth/helper_test.go | 14 +++---- 7 files changed, 100 insertions(+), 89 deletions(-) (limited to 'eth') diff --git a/eth/api.go b/eth/api.go index b64153fd7..58ae27df2 100644 --- a/eth/api.go +++ b/eth/api.go @@ -26,7 +26,6 @@ import ( "io/ioutil" "math/big" "os" - "runtime" "strings" "time" @@ -37,6 +36,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" @@ -56,18 +56,18 @@ func NewPublicEthereumAPI(e *Ethereum) *PublicEthereumAPI { } // Etherbase is the address that mining rewards will be send to -func (s *PublicEthereumAPI) Etherbase() (common.Address, error) { - return s.e.Etherbase() +func (api *PublicEthereumAPI) Etherbase() (common.Address, error) { + return api.e.Etherbase() } // Coinbase is the address that mining rewards will be send to (alias for Etherbase) -func (s *PublicEthereumAPI) Coinbase() (common.Address, error) { - return s.Etherbase() +func (api *PublicEthereumAPI) Coinbase() (common.Address, error) { + return api.Etherbase() } // Hashrate returns the POW hashrate -func (s *PublicEthereumAPI) Hashrate() hexutil.Uint64 { - return hexutil.Uint64(s.e.Miner().HashRate()) +func (api *PublicEthereumAPI) Hashrate() hexutil.Uint64 { + return hexutil.Uint64(api.e.Miner().HashRate()) } // PublicMinerAPI provides an API to control the miner. @@ -79,34 +79,34 @@ type PublicMinerAPI struct { // NewPublicMinerAPI create a new PublicMinerAPI instance. func NewPublicMinerAPI(e *Ethereum) *PublicMinerAPI { - agent := miner.NewRemoteAgent(e.Pow()) + agent := miner.NewRemoteAgent(e.BlockChain(), e.Engine()) e.Miner().Register(agent) return &PublicMinerAPI{e, agent} } // Mining returns an indication if this node is currently mining. -func (s *PublicMinerAPI) Mining() bool { - return s.e.IsMining() +func (api *PublicMinerAPI) Mining() bool { + return api.e.IsMining() } // SubmitWork can be used by external miner to submit their POW solution. It returns an indication if the work was // accepted. Note, this is not an indication if the provided work was valid! -func (s *PublicMinerAPI) SubmitWork(nonce types.BlockNonce, solution, digest common.Hash) bool { - return s.agent.SubmitWork(nonce, digest, solution) +func (api *PublicMinerAPI) SubmitWork(nonce types.BlockNonce, solution, digest common.Hash) bool { + return api.agent.SubmitWork(nonce, digest, solution) } // GetWork returns a work package for external miner. The work package consists of 3 strings // result[0], 32 bytes hex encoded current block header pow-hash // result[1], 32 bytes hex encoded seed hash used for DAG // result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty -func (s *PublicMinerAPI) GetWork() ([3]string, error) { - if !s.e.IsMining() { - if err := s.e.StartMining(0); err != nil { +func (api *PublicMinerAPI) GetWork() ([3]string, error) { + if !api.e.IsMining() { + if err := api.e.StartMining(); err != nil { return [3]string{}, err } } - work, err := s.agent.GetWork() + work, err := api.agent.GetWork() if err != nil { return work, fmt.Errorf("mining not ready: %v", err) } @@ -116,8 +116,8 @@ func (s *PublicMinerAPI) GetWork() ([3]string, error) { // SubmitHashrate can be used for remote miners to submit their hash rate. This enables the node to report the combined // hash rate of all miners which submit work through this node. It accepts the miner hash rate and an identifier which // must be unique between nodes. -func (s *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool { - s.agent.SubmitHashrate(id, uint64(hashrate)) +func (api *PublicMinerAPI) SubmitHashrate(hashrate hexutil.Uint64, id common.Hash) bool { + api.agent.SubmitHashrate(id, uint64(hashrate)) return true } @@ -132,47 +132,59 @@ func NewPrivateMinerAPI(e *Ethereum) *PrivateMinerAPI { return &PrivateMinerAPI{e: e} } -// Start the miner with the given number of threads. If threads is nil the number of -// workers started is equal to the number of logical CPU's that are usable by this process. -func (s *PrivateMinerAPI) Start(threads *int) (bool, error) { - var err error - if threads == nil { - err = s.e.StartMining(runtime.NumCPU()) - } else { - err = s.e.StartMining(*threads) +// Start the miner with the given number of threads. If threads is nil the number +// of workers started is equal to the number of logical CPUs that are usable by +// this process. If mining is already running, this method adjust the number of +// threads allowed to use. +func (api *PrivateMinerAPI) Start(threads *int) error { + // Set the number of threads if the seal engine supports it + if threads != nil { + type threaded interface { + SetThreads(threads int) + } + if th, ok := api.e.engine.(threaded); ok { + log.Info("Updated mining threads", "threads", *threads) + th.SetThreads(*threads) + } else { + log.Warn("Current seal engine isn't threaded") + } } - return err == nil, err + // Start the miner and return + if !api.e.IsMining() { + return api.e.StartMining() + } + return nil } // Stop the miner -func (s *PrivateMinerAPI) Stop() bool { - s.e.StopMining() +func (api *PrivateMinerAPI) Stop() bool { + api.e.StopMining() return true } // SetExtra sets the extra data string that is included when this miner mines a block. -func (s *PrivateMinerAPI) SetExtra(extra string) (bool, error) { - if err := s.e.Miner().SetExtra([]byte(extra)); err != nil { +func (api *PrivateMinerAPI) SetExtra(extra string) (bool, error) { + if err := api.e.Miner().SetExtra([]byte(extra)); err != nil { return false, err } return true, nil } // SetGasPrice sets the minimum accepted gas price for the miner. -func (s *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { - s.e.Miner().SetGasPrice((*big.Int)(&gasPrice)) +func (api *PrivateMinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { + api.e.Miner().SetGasPrice((*big.Int)(&gasPrice)) return true } // SetEtherbase sets the etherbase of the miner -func (s *PrivateMinerAPI) SetEtherbase(etherbase common.Address) bool { - s.e.SetEtherbase(etherbase) +func (api *PrivateMinerAPI) SetEtherbase(etherbase common.Address) bool { + api.e.SetEtherbase(etherbase) return true } // GetHashrate returns the current hashrate of the miner. -func (s *PrivateMinerAPI) GetHashrate() uint64 { - return uint64(s.e.miner.HashRate()) +func (api *PrivateMinerAPI) GetHashrate() uint64 { + return uint64(api.e.miner.HashRate()) } // PrivateAdminAPI is the collection of Etheruem full node-related APIs @@ -321,7 +333,7 @@ type TraceArgs struct { Timeout *string } -// TraceBlock processes the given block's RLP but does not import the block in to +// TraceBlock processes the given block'api RLP but does not import the block in to // the chain. func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.LogConfig) BlockTraceResult { var block types.Block @@ -338,7 +350,7 @@ func (api *PrivateDebugAPI) TraceBlock(blockRlp []byte, config *vm.LogConfig) Bl } } -// TraceBlockFromFile loads the block's RLP from the given file name and attempts to +// TraceBlockFromFile loads the block'api RLP from the given file name and attempts to // process it but does not import the block in to the chain. func (api *PrivateDebugAPI) TraceBlockFromFile(file string, config *vm.LogConfig) BlockTraceResult { blockRlp, err := ioutil.ReadFile(file) @@ -395,8 +407,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConf Debug: true, Tracer: structLogger, } - - if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash(), block.NumberU64()-1), true, false); err != nil { + if err := api.eth.engine.VerifyHeader(blockchain, block.Header(), true); err != nil { return false, structLogger.StructLogs(), err } statedb, err := blockchain.StateAt(blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1).Root()) diff --git a/eth/backend.go b/eth/backend.go index b8df98976..af1d46a2c 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -22,10 +22,11 @@ import ( "math/big" "regexp" "sync" - "time" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -40,18 +41,9 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/rpc" ) -const ( - epochLength = 30000 - ethashRevision = 23 - - autoDAGcheckInterval = 10 * time.Hour - autoDAGepochHeight = epochLength / 2 -) - var ( datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true} portInUseErrRE = regexp.MustCompile("address already in use") @@ -124,7 +116,7 @@ type Ethereum struct { chainDb ethdb.Database // Block chain database eventMux *event.TypeMux - pow pow.PoW + engine consensus.Engine accountManager *accounts.Manager ApiBackend *EthApiBackend @@ -163,7 +155,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { chainConfig: chainConfig, eventMux: ctx.EventMux, accountManager: ctx.AccountManager, - pow: CreatePoW(ctx, config), + engine: CreateConsensusEngine(ctx, config, chainConfig, chainDb), shutdownChan: make(chan bool), stopDbUpgrade: stopDbUpgrade, netVersionId: config.NetworkId, @@ -186,7 +178,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } vmConfig := vm.Config{EnablePreimageRecording: config.EnablePreimageRecording} - eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.pow, eth.eventMux, vmConfig) + eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.engine, eth.eventMux, vmConfig) if err != nil { return nil, err } @@ -211,10 +203,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } } - if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, maxPeers, eth.eventMux, eth.txPool, eth.pow, eth.blockchain, chainDb); err != nil { + if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.FastSync, config.NetworkId, maxPeers, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil { return nil, err } - eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.pow) + + eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine) eth.miner.SetGasPrice(config.GasPrice) eth.miner.SetExtra(config.ExtraData) @@ -241,20 +234,20 @@ func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Data return db, err } -// CreatePoW creates the required type of PoW instance for an Ethereum service -func CreatePoW(ctx *node.ServiceContext, config *Config) pow.PoW { +// CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service +func CreateConsensusEngine(ctx *node.ServiceContext, config *Config, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine { switch { case config.PowFake: log.Warn("Ethash used in fake mode") - return pow.FakePow{} + return ethash.NewFaker() case config.PowTest: log.Warn("Ethash used in test mode") - return pow.NewTestEthash() + return ethash.NewTester() case config.PowShared: log.Warn("Ethash used in shared mode") - return pow.NewSharedEthash() + return ethash.NewShared() default: - return pow.NewFullEthash(ctx.ResolvePath(config.EthashCacheDir), config.EthashCachesInMem, config.EthashCachesOnDisk, + return ethash.New(ctx.ResolvePath(config.EthashCacheDir), config.EthashCachesInMem, config.EthashCachesOnDisk, config.EthashDatasetDir, config.EthashDatasetsInMem, config.EthashDatasetsOnDisk) } } @@ -262,7 +255,13 @@ func CreatePoW(ctx *node.ServiceContext, config *Config) pow.PoW { // APIs returns the collection of RPC services the ethereum package offers. // NOTE, some of these services probably need to be moved to somewhere else. func (s *Ethereum) APIs() []rpc.API { - return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{ + apis := ethapi.GetAPIs(s.ApiBackend, s.solcPath) + + // Append any APIs exposed explicitly by the consensus engine + apis = append(apis, s.engine.APIs(s.BlockChain())...) + + // Append all the local APIs and return + return append(apis, []rpc.API{ { Namespace: "eth", Version: "1.0", @@ -332,13 +331,13 @@ func (self *Ethereum) SetEtherbase(etherbase common.Address) { self.miner.SetEtherbase(etherbase) } -func (s *Ethereum) StartMining(threads int) error { +func (s *Ethereum) StartMining() error { eb, err := s.Etherbase() if err != nil { log.Error("Cannot start mining without etherbase", "err", err) return fmt.Errorf("etherbase missing: %v", err) } - go s.miner.Start(eb, threads) + go s.miner.Start(eb) return nil } @@ -350,7 +349,7 @@ func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } -func (s *Ethereum) Pow() pow.PoW { return s.pow } +func (s *Ethereum) Engine() consensus.Engine { return s.engine } func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } func (s *Ethereum) IsListening() bool { return true } // Always listening func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } diff --git a/eth/fetcher/fetcher.go b/eth/fetcher/fetcher.go index d82f4f3e6..64a991069 100644 --- a/eth/fetcher/fetcher.go +++ b/eth/fetcher/fetcher.go @@ -52,8 +52,8 @@ type headerRequesterFn func(common.Hash) error // bodyRequesterFn is a callback type for sending a body retrieval request. type bodyRequesterFn func([]common.Hash) error -// blockValidatorFn is a callback type to verify a block's header for fast propagation. -type blockValidatorFn func(block *types.Block, parent *types.Block) error +// headerVerifierFn is a callback type to verify a block's header for fast propagation. +type headerVerifierFn func(header *types.Header) error // blockBroadcasterFn is a callback type for broadcasting a block to connected peers. type blockBroadcasterFn func(block *types.Block, propagate bool) @@ -129,7 +129,7 @@ type Fetcher struct { // Callbacks getBlock blockRetrievalFn // Retrieves a block from the local chain - validateBlock blockValidatorFn // Checks if a block's headers have a valid proof of work + verifyHeader headerVerifierFn // Checks if a block's headers have a valid proof of work broadcastBlock blockBroadcasterFn // Broadcasts a block to connected peers chainHeight chainHeightFn // Retrieves the current chain's height insertChain chainInsertFn // Injects a batch of blocks into the chain @@ -144,7 +144,7 @@ type Fetcher struct { } // New creates a block fetcher to retrieve blocks based on hash announcements. -func New(getBlock blockRetrievalFn, validateBlock blockValidatorFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher { +func New(getBlock blockRetrievalFn, verifyHeader headerVerifierFn, broadcastBlock blockBroadcasterFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher { return &Fetcher{ notify: make(chan *announce), inject: make(chan *inject), @@ -162,7 +162,7 @@ func New(getBlock blockRetrievalFn, validateBlock blockValidatorFn, broadcastBlo queues: make(map[string]int), queued: make(map[common.Hash]*inject), getBlock: getBlock, - validateBlock: validateBlock, + verifyHeader: verifyHeader, broadcastBlock: broadcastBlock, chainHeight: chainHeight, insertChain: insertChain, @@ -648,7 +648,7 @@ func (f *Fetcher) insert(peer string, block *types.Block) { return } // Quickly validate the header and propagate the block if it passes - switch err := f.validateBlock(block, parent); err { + switch err := f.verifyHeader(block.Header()); err { case nil: // All ok, quickly propagate to our peers propBroadcastOutTimer.UpdateSince(block.ReceivedAt) diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go index 7a94241c6..85d2f8645 100644 --- a/eth/fetcher/fetcher_test.go +++ b/eth/fetcher/fetcher_test.go @@ -91,7 +91,7 @@ func newTester() *fetcherTester { blocks: map[common.Hash]*types.Block{genesis.Hash(): genesis}, drops: make(map[string]bool), } - tester.fetcher = New(tester.getBlock, tester.verifyBlock, tester.broadcastBlock, tester.chainHeight, tester.insertChain, tester.dropPeer) + tester.fetcher = New(tester.getBlock, tester.verifyHeader, tester.broadcastBlock, tester.chainHeight, tester.insertChain, tester.dropPeer) tester.fetcher.Start() return tester @@ -105,8 +105,8 @@ func (f *fetcherTester) getBlock(hash common.Hash) *types.Block { return f.blocks[hash] } -// verifyBlock is a nop placeholder for the block header verification. -func (f *fetcherTester) verifyBlock(block *types.Block, parent *types.Block) error { +// verifyHeader is a nop placeholder for the block header verification. +func (f *fetcherTester) verifyHeader(header *types.Header) error { return nil } diff --git a/eth/handler.go b/eth/handler.go index ade8f7719..445272060 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -27,6 +27,8 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/downloader" @@ -37,7 +39,6 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/pow" "github.com/ethereum/go-ethereum/rlp" ) @@ -97,7 +98,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(config *params.ChainConfig, fastSync bool, networkId int, maxPeers int, mux *event.TypeMux, txpool txPool, pow pow.PoW, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { +func NewProtocolManager(config *params.ChainConfig, fastSync bool, networkId int, maxPeers int, mux *event.TypeMux, txpool txPool, engine consensus.Engine, blockchain *core.BlockChain, chaindb ethdb.Database) (*ProtocolManager, error) { // Create the protocol manager with the base fields manager := &ProtocolManager{ networkId: networkId, @@ -165,8 +166,8 @@ func NewProtocolManager(config *params.ChainConfig, fastSync bool, networkId int blockchain.GetTdByHash, blockchain.InsertHeaderChain, manager.insertChain, blockchain.InsertReceiptChain, blockchain.Rollback, manager.removePeer) - validator := func(block *types.Block, parent *types.Block) error { - return core.ValidateHeader(config, pow, block.Header(), parent.Header(), true, false) + validator := func(header *types.Header) error { + return engine.VerifyHeader(blockchain, header, true) } heighter := func() uint64 { return blockchain.CurrentBlock().NumberU64() @@ -448,7 +449,7 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { p.forkDrop = nil // Validate the header and either drop the peer or continue - if err := core.ValidateDAOHeaderExtraData(pm.chainconfig, headers[0]); err != nil { + if err := misc.VerifyDAOHeaderExtraData(pm.chainconfig, headers[0]); err != nil { p.Log().Debug("Verified to be on the other side of the DAO fork, dropping") return err } diff --git a/eth/handler_test.go b/eth/handler_test.go index 31435b331..f85d730b6 100644 --- a/eth/handler_test.go +++ b/eth/handler_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -34,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/pow" ) var bigTxGas = new(big.Int).SetUint64(params.TxGas) @@ -469,7 +469,7 @@ func testDAOChallenge(t *testing.T, localForked, remoteForked bool, timeout bool // Create a DAO aware protocol manager var ( evmux = new(event.TypeMux) - pow = new(pow.FakePow) + pow = ethash.NewFaker() db, _ = ethdb.NewMemDatabase() config = ¶ms.ChainConfig{DAOForkBlock: big.NewInt(1), DAOForkSupport: localForked} gspec = &core.Genesis{Config: config} diff --git a/eth/helper_test.go b/eth/helper_test.go index e67b49691..a8c538e6c 100644 --- a/eth/helper_test.go +++ b/eth/helper_test.go @@ -28,6 +28,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -37,7 +38,6 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/discover" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/pow" ) var ( @@ -50,22 +50,22 @@ var ( // channels for different events. func newTestProtocolManager(fastSync bool, blocks int, generator func(int, *core.BlockGen), newtx chan<- []*types.Transaction) (*ProtocolManager, error) { var ( - evmux = new(event.TypeMux) - pow = new(pow.FakePow) - db, _ = ethdb.NewMemDatabase() - gspec = &core.Genesis{ + evmux = new(event.TypeMux) + engine = ethash.NewFaker() + db, _ = ethdb.NewMemDatabase() + 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{}) + blockchain, _ = core.NewBlockChain(db, gspec.Config, engine, evmux, vm.Config{}) ) chain, _ := core.GenerateChain(gspec.Config, genesis, db, blocks, generator) if _, err := blockchain.InsertChain(chain); err != nil { panic(err) } - pm, err := NewProtocolManager(gspec.Config, fastSync, NetworkId, 1000, evmux, &testTxPool{added: newtx}, pow, blockchain, db) + pm, err := NewProtocolManager(gspec.Config, fastSync, NetworkId, 1000, evmux, &testTxPool{added: newtx}, engine, blockchain, db) if err != nil { return nil, err } -- cgit