github.com/pfcoder/quorum@v2.0.3-0.20180501191142-d4a1b0958135+incompatible/eth/backend.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package eth implements the Ethereum protocol. 18 package eth 19 20 import ( 21 "errors" 22 "fmt" 23 "math/big" 24 "runtime" 25 "sync" 26 "sync/atomic" 27 28 "github.com/ethereum/go-ethereum/accounts" 29 "github.com/ethereum/go-ethereum/common" 30 "github.com/ethereum/go-ethereum/common/hexutil" 31 "github.com/ethereum/go-ethereum/consensus" 32 "github.com/ethereum/go-ethereum/consensus/clique" 33 "github.com/ethereum/go-ethereum/consensus/ethash" 34 "github.com/ethereum/go-ethereum/consensus/istanbul" 35 istanbulBackend "github.com/ethereum/go-ethereum/consensus/istanbul/backend" 36 "github.com/ethereum/go-ethereum/core" 37 "github.com/ethereum/go-ethereum/core/bloombits" 38 "github.com/ethereum/go-ethereum/core/types" 39 "github.com/ethereum/go-ethereum/core/vm" 40 "github.com/ethereum/go-ethereum/crypto" 41 "github.com/ethereum/go-ethereum/eth/downloader" 42 "github.com/ethereum/go-ethereum/eth/filters" 43 "github.com/ethereum/go-ethereum/eth/gasprice" 44 "github.com/ethereum/go-ethereum/ethdb" 45 "github.com/ethereum/go-ethereum/event" 46 "github.com/ethereum/go-ethereum/internal/ethapi" 47 "github.com/ethereum/go-ethereum/log" 48 "github.com/ethereum/go-ethereum/miner" 49 "github.com/ethereum/go-ethereum/node" 50 "github.com/ethereum/go-ethereum/p2p" 51 "github.com/ethereum/go-ethereum/params" 52 "github.com/ethereum/go-ethereum/rlp" 53 "github.com/ethereum/go-ethereum/rpc" 54 ) 55 56 type LesServer interface { 57 Start(srvr *p2p.Server) 58 Stop() 59 Protocols() []p2p.Protocol 60 } 61 62 // Ethereum implements the Ethereum full node service. 63 type Ethereum struct { 64 config *Config 65 chainConfig *params.ChainConfig 66 67 // Channel for shutting down the service 68 shutdownChan chan bool // Channel for shutting down the ethereum 69 stopDbUpgrade func() error // stop chain db sequential key upgrade 70 71 // Handlers 72 txPool *core.TxPool 73 blockchain *core.BlockChain 74 protocolManager *ProtocolManager 75 lesServer LesServer 76 77 // DB interfaces 78 chainDb ethdb.Database // Block chain database 79 80 eventMux *event.TypeMux 81 engine consensus.Engine 82 accountManager *accounts.Manager 83 84 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 85 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 86 87 ApiBackend *EthApiBackend 88 89 miner *miner.Miner 90 gasPrice *big.Int 91 etherbase common.Address 92 93 networkId uint64 94 netRPCService *ethapi.PublicNetAPI 95 96 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 97 } 98 99 // HACK(joel) this was added just to make the eth chain config visible to RegisterRaftService 100 func (s *Ethereum) ChainConfig() *params.ChainConfig { 101 return s.chainConfig 102 } 103 104 func (s *Ethereum) AddLesServer(ls LesServer) { 105 s.lesServer = ls 106 } 107 108 // New creates a new Ethereum object (including the 109 // initialisation of the common Ethereum object) 110 func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { 111 if config.SyncMode == downloader.LightSync { 112 return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") 113 } 114 if !config.SyncMode.IsValid() { 115 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 116 } 117 chainDb, err := CreateDB(ctx, config, "chaindata") 118 if err != nil { 119 return nil, err 120 } 121 stopDbUpgrade := upgradeDeduplicateData(chainDb) 122 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) 123 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 124 return nil, genesisErr 125 } 126 log.Info("Initialised chain configuration", "config", chainConfig) 127 128 eth := &Ethereum{ 129 config: config, 130 chainDb: chainDb, 131 chainConfig: chainConfig, 132 eventMux: ctx.EventMux, 133 accountManager: ctx.AccountManager, 134 engine: CreateConsensusEngine(ctx, config, chainConfig, chainDb), 135 shutdownChan: make(chan bool), 136 stopDbUpgrade: stopDbUpgrade, 137 networkId: config.NetworkId, 138 gasPrice: config.GasPrice, 139 etherbase: config.Etherbase, 140 bloomRequests: make(chan chan *bloombits.Retrieval), 141 bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks), 142 } 143 144 // force to set the istanbul etherbase to node key address 145 if chainConfig.Istanbul != nil { 146 eth.etherbase = crypto.PubkeyToAddress(ctx.NodeKey().PublicKey) 147 } 148 149 log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId) 150 151 if !config.SkipBcVersionCheck { 152 bcVersion := core.GetBlockChainVersion(chainDb) 153 if bcVersion != core.BlockChainVersion && bcVersion != 0 { 154 return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, core.BlockChainVersion) 155 } 156 core.WriteBlockChainVersion(chainDb, core.BlockChainVersion) 157 } 158 159 vmConfig := vm.Config{EnablePreimageRecording: config.EnablePreimageRecording} 160 eth.blockchain, err = core.NewBlockChain(chainDb, eth.chainConfig, eth.engine, vmConfig) 161 if err != nil { 162 return nil, err 163 } 164 // Rewind the chain in case of an incompatible config upgrade. 165 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 166 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 167 eth.blockchain.SetHead(compat.RewindTo) 168 core.WriteChainConfig(chainDb, genesisHash, chainConfig) 169 } 170 eth.bloomIndexer.Start(eth.blockchain.CurrentHeader(), eth.blockchain.SubscribeChainEvent) 171 172 if config.TxPool.Journal != "" { 173 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 174 } 175 eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) 176 177 if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb, config.RaftMode); err != nil { 178 return nil, err 179 } 180 eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine) 181 eth.miner.SetExtra(makeExtraData(config.ExtraData, eth.chainConfig.IsQuorum)) 182 183 eth.ApiBackend = &EthApiBackend{eth, nil} 184 gpoParams := config.GPO 185 if gpoParams.Default == nil { 186 gpoParams.Default = config.GasPrice 187 } 188 eth.ApiBackend.gpo = gasprice.NewOracle(eth.ApiBackend, gpoParams) 189 190 return eth, nil 191 } 192 193 func makeExtraData(extra []byte, isQuorum bool) []byte { 194 if len(extra) == 0 { 195 // create default extradata 196 extra, _ = rlp.EncodeToBytes([]interface{}{ 197 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 198 "geth", 199 runtime.Version(), 200 runtime.GOOS, 201 }) 202 } 203 if uint64(len(extra)) > params.GetMaximumExtraDataSize(isQuorum) { 204 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.GetMaximumExtraDataSize(isQuorum)) 205 extra = nil 206 } 207 return extra 208 } 209 210 // CreateDB creates the chain database. 211 func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) { 212 db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles) 213 if err != nil { 214 return nil, err 215 } 216 if db, ok := db.(*ethdb.LDBDatabase); ok { 217 db.Meter("eth/db/chaindata/") 218 } 219 return db, nil 220 } 221 222 // CreateConsensusEngine creates the required type of consensus engine instance for an Ethereum service 223 func CreateConsensusEngine(ctx *node.ServiceContext, config *Config, chainConfig *params.ChainConfig, db ethdb.Database) consensus.Engine { 224 // If proof-of-authority is requested, set it up 225 if chainConfig.Clique != nil { 226 return clique.New(chainConfig.Clique, db) 227 } 228 // If Istanbul is requested, set it up 229 if chainConfig.Istanbul != nil { 230 if chainConfig.Istanbul.Epoch != 0 { 231 config.Istanbul.Epoch = chainConfig.Istanbul.Epoch 232 } 233 config.Istanbul.ProposerPolicy = istanbul.ProposerPolicy(chainConfig.Istanbul.ProposerPolicy) 234 return istanbulBackend.New(&config.Istanbul, ctx.NodeKey(), db) 235 } 236 237 // Otherwise assume proof-of-work 238 switch { 239 case config.PowFake: 240 log.Warn("Ethash used in fake mode") 241 return ethash.NewFaker() 242 case config.PowTest: 243 log.Warn("Ethash used in test mode") 244 return ethash.NewTester() 245 case config.PowShared: 246 log.Warn("Ethash used in shared mode") 247 return ethash.NewShared() 248 default: 249 // For Quorum, Raft run as a separate service, so 250 // the Ethereum service still needs a consensus engine, 251 // use the consensus with the lightest overhead 252 log.Warn("Ethash used in full fake mode") 253 return ethash.NewFullFaker() 254 } 255 } 256 257 // APIs returns the collection of RPC services the ethereum package offers. 258 // NOTE, some of these services probably need to be moved to somewhere else. 259 func (s *Ethereum) APIs() []rpc.API { 260 apis := ethapi.GetAPIs(s.ApiBackend) 261 262 // Append any APIs exposed explicitly by the consensus engine 263 apis = append(apis, s.engine.APIs(s.BlockChain())...) 264 265 // Append all the local APIs and return 266 return append(apis, []rpc.API{ 267 { 268 Namespace: "eth", 269 Version: "1.0", 270 Service: NewPublicEthereumAPI(s), 271 Public: true, 272 }, { 273 Namespace: "eth", 274 Version: "1.0", 275 Service: NewPublicMinerAPI(s), 276 Public: true, 277 }, { 278 Namespace: "eth", 279 Version: "1.0", 280 Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), 281 Public: true, 282 }, { 283 Namespace: "miner", 284 Version: "1.0", 285 Service: NewPrivateMinerAPI(s), 286 Public: false, 287 }, { 288 Namespace: "eth", 289 Version: "1.0", 290 Service: filters.NewPublicFilterAPI(s.ApiBackend, false), 291 Public: true, 292 }, { 293 Namespace: "admin", 294 Version: "1.0", 295 Service: NewPrivateAdminAPI(s), 296 }, { 297 Namespace: "debug", 298 Version: "1.0", 299 Service: NewPublicDebugAPI(s), 300 Public: true, 301 }, { 302 Namespace: "debug", 303 Version: "1.0", 304 Service: NewPrivateDebugAPI(s.chainConfig, s), 305 }, { 306 Namespace: "net", 307 Version: "1.0", 308 Service: s.netRPCService, 309 Public: true, 310 }, 311 }...) 312 } 313 314 func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 315 s.blockchain.ResetWithGenesisBlock(gb) 316 } 317 318 func (s *Ethereum) Etherbase() (eb common.Address, err error) { 319 s.lock.RLock() 320 etherbase := s.etherbase 321 s.lock.RUnlock() 322 323 if etherbase != (common.Address{}) { 324 return etherbase, nil 325 } 326 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 327 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 328 return accounts[0].Address, nil 329 } 330 } 331 return common.Address{}, fmt.Errorf("etherbase address must be explicitly specified") 332 } 333 334 // set in js console via admin interface or wrapper from cli flags 335 func (self *Ethereum) SetEtherbase(etherbase common.Address) { 336 self.lock.Lock() 337 if _, ok := self.engine.(consensus.Istanbul); ok { 338 log.Error("Cannot set etherbase in Istanbul consensus") 339 return 340 } 341 self.etherbase = etherbase 342 self.lock.Unlock() 343 344 self.miner.SetEtherbase(etherbase) 345 } 346 347 func (s *Ethereum) StartMining(local bool) error { 348 eb, err := s.Etherbase() 349 if err != nil { 350 log.Error("Cannot start mining without etherbase", "err", err) 351 return fmt.Errorf("etherbase missing: %v", err) 352 } 353 if clique, ok := s.engine.(*clique.Clique); ok { 354 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) 355 if wallet == nil || err != nil { 356 log.Error("Etherbase account unavailable locally", "err", err) 357 return fmt.Errorf("signer missing: %v", err) 358 } 359 clique.Authorize(eb, wallet.SignHash) 360 } 361 if local { 362 // If local (CPU) mining is started, we can disable the transaction rejection 363 // mechanism introduced to speed sync times. CPU mining on mainnet is ludicrous 364 // so noone will ever hit this path, whereas marking sync done on CPU mining 365 // will ensure that private networks work in single miner mode too. 366 atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) 367 } 368 go s.miner.Start(eb) 369 return nil 370 } 371 372 func (s *Ethereum) StopMining() { s.miner.Stop() } 373 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 374 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 375 376 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 377 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 378 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 379 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 380 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 381 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 382 func (s *Ethereum) IsListening() bool { return true } // Always listening 383 func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } 384 func (s *Ethereum) NetVersion() uint64 { return s.networkId } 385 func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } 386 387 // Protocols implements node.Service, returning all the currently configured 388 // network protocols to start. 389 func (s *Ethereum) Protocols() []p2p.Protocol { 390 if s.lesServer == nil { 391 return s.protocolManager.SubProtocols 392 } 393 return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...) 394 } 395 396 // Start implements node.Service, starting all internal goroutines needed by the 397 // Ethereum protocol implementation. 398 func (s *Ethereum) Start(srvr *p2p.Server) error { 399 // Start the bloom bits servicing goroutines 400 s.startBloomHandlers() 401 402 // Start the RPC service 403 s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion()) 404 405 // Figure out a max peers count based on the server limits 406 maxPeers := srvr.MaxPeers 407 if s.config.LightServ > 0 { 408 maxPeers -= s.config.LightPeers 409 if maxPeers < srvr.MaxPeers/2 { 410 maxPeers = srvr.MaxPeers / 2 411 } 412 } 413 // Start the networking layer and the light server if requested 414 s.protocolManager.Start(maxPeers) 415 if s.lesServer != nil { 416 s.lesServer.Start(srvr) 417 } 418 return nil 419 } 420 421 // Stop implements node.Service, terminating all internal goroutines used by the 422 // Ethereum protocol. 423 func (s *Ethereum) Stop() error { 424 if s.stopDbUpgrade != nil { 425 s.stopDbUpgrade() 426 } 427 s.bloomIndexer.Close() 428 s.blockchain.Stop() 429 s.protocolManager.Stop() 430 if s.lesServer != nil { 431 s.lesServer.Stop() 432 } 433 s.txPool.Stop() 434 s.miner.Stop() 435 s.eventMux.Stop() 436 437 s.chainDb.Close() 438 close(s.shutdownChan) 439 440 return nil 441 }