github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/eth/backend.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 12:09:38</date> 10 //</624342633153564672> 11 12 13 //包ETH实现以太坊协议。 14 package eth 15 16 import ( 17 "errors" 18 "fmt" 19 "math/big" 20 "runtime" 21 "sync" 22 "sync/atomic" 23 24 "github.com/ethereum/go-ethereum/accounts" 25 "github.com/ethereum/go-ethereum/common" 26 "github.com/ethereum/go-ethereum/common/hexutil" 27 "github.com/ethereum/go-ethereum/consensus" 28 //“github.com/ethereum/go-ethereum/consension/clique” 29 "github.com/ethereum/go-ethereum/consensus/dpos" 30 "github.com/ethereum/go-ethereum/core" 31 "github.com/ethereum/go-ethereum/core/bloombits" 32 "github.com/ethereum/go-ethereum/core/rawdb" 33 "github.com/ethereum/go-ethereum/core/types" 34 "github.com/ethereum/go-ethereum/core/vm" 35 "github.com/ethereum/go-ethereum/eth/downloader" 36 "github.com/ethereum/go-ethereum/eth/filters" 37 "github.com/ethereum/go-ethereum/eth/gasprice" 38 "github.com/ethereum/go-ethereum/ethdb" 39 "github.com/ethereum/go-ethereum/event" 40 "github.com/ethereum/go-ethereum/internal/ethapi" 41 "github.com/ethereum/go-ethereum/log" 42 "github.com/ethereum/go-ethereum/miner" 43 "github.com/ethereum/go-ethereum/node" 44 "github.com/ethereum/go-ethereum/p2p" 45 "github.com/ethereum/go-ethereum/params" 46 "github.com/ethereum/go-ethereum/rlp" 47 "github.com/ethereum/go-ethereum/rpc" 48 ) 49 50 51 type LesServer interface { 52 Start(srvr *p2p.Server) 53 Stop() 54 Protocols() []p2p.Protocol 55 SetBloomBitsIndexer(bbIndexer *core.ChainIndexer) 56 } 57 58 //以太坊实施以太坊全节点服务。 59 type Ethereum struct { 60 config *Config 61 chainConfig *params.ChainConfig 62 63 //关闭服务的通道 64 shutdownChan chan bool //关闭以太坊的通道 65 66 //处理程序 67 txPool *core.TxPool 68 blockchain *core.BlockChain 69 protocolManager *ProtocolManager 70 lesServer LesServer 71 72 //数据库接口 73 chainDb ethdb.Database //区块链数据库 74 75 eventMux *event.TypeMux 76 engine consensus.Engine 77 accountManager *accounts.Manager 78 79 bloomRequests chan chan *bloombits.Retrieval //接收Bloom数据检索请求的通道 80 bloomIndexer *core.ChainIndexer //块导入期间的Bloom索引器操作 81 82 APIBackend *EthAPIBackend 83 84 miner *miner.Miner 85 gasPrice *big.Int 86 validator common.Address 87 coinbase common.Address 88 89 networkID uint64 90 netRPCService *ethapi.PublicNetAPI 91 92 lock sync.RWMutex //保护可变油田(如天然气价格和Coinbase) 93 } 94 95 func (s *Ethereum) AddLesServer(ls LesServer) { 96 s.lesServer = ls 97 ls.SetBloomBitsIndexer(s.bloomIndexer) 98 } 99 100 //新建创建新的以太坊对象(包括 101 //公共EythUM对象的初始化 102 func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { 103 if config.SyncMode == downloader.LightSync { 104 return nil, errors.New("can't run eth.Ethereum in light sync mode, use les.LightEthereum") 105 } 106 if !config.SyncMode.IsValid() { 107 return nil, fmt.Errorf("invalid sync mode %d", config.SyncMode) 108 } 109 chainDb, err := CreateDB(ctx, config, "chaindata") 110 if err != nil { 111 return nil, err 112 } 113 chainConfig, genesisHash, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) 114 if _, ok := genesisErr.(*params.ConfigCompatError); genesisErr != nil && !ok { 115 return nil, genesisErr 116 } 117 118 log.Info("Initialised chain configuration", "config", chainConfig) 119 120 eth := &Ethereum{ 121 config: config, 122 chainDb: chainDb, 123 chainConfig: chainConfig, 124 eventMux: ctx.EventMux, 125 accountManager: ctx.AccountManager, 126 engine: dpos.New(chainConfig.Dpos, chainDb), 127 shutdownChan: make(chan bool), 128 networkID: config.NetworkId, 129 gasPrice: config.MinerGasPrice, 130 validator: config.Validator, 131 coinbase: config.Coinbase, 132 bloomRequests: make(chan chan *bloombits.Retrieval), 133 bloomIndexer: NewBloomIndexer(chainDb, params.BloomBitsBlocks, bloomConfirms), 134 } 135 136 log.Info("Initialising Ethereum protocol", "versions", ProtocolVersions, "network", config.NetworkId) 137 if !config.SkipBcVersionCheck { 138 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 139 if bcVersion != core.BlockChainVersion && bcVersion != 0 { 140 return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d).\n", bcVersion, core.BlockChainVersion) 141 } 142 rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) 143 } 144 var ( 145 vmConfig = vm.Config{EnablePreimageRecording: config.EnablePreimageRecording} 146 cacheConfig = &core.CacheConfig{Disabled: config.NoPruning, TrieNodeLimit: config.TrieCache, TrieTimeLimit: config.TrieTimeout} 147 ) 148 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, eth.chainConfig, eth.engine, vmConfig) 149 if err != nil { 150 return nil, err 151 } 152 //在不兼容的配置升级时倒带链。 153 if compat, ok := genesisErr.(*params.ConfigCompatError); ok { 154 log.Warn("Rewinding chain to upgrade configuration", "err", compat) 155 eth.blockchain.SetHead(compat.RewindTo) 156 rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig) 157 } 158 eth.bloomIndexer.Start(eth.blockchain) 159 160 if config.TxPool.Journal != "" { 161 config.TxPool.Journal = ctx.ResolvePath(config.TxPool.Journal) 162 } 163 eth.txPool = core.NewTxPool(config.TxPool, eth.chainConfig, eth.blockchain) 164 165 if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil { 166 return nil, err 167 } 168 169 eth.miner = miner.New(eth, eth.chainConfig, eth.EventMux(), eth.engine, config.MinerRecommit) 170 eth.miner.SetExtra(makeExtraData(config.MinerExtraData)) 171 172 eth.APIBackend = &EthAPIBackend{eth, nil} 173 gpoParams := config.GPO 174 if gpoParams.Default == nil { 175 gpoParams.Default = config.MinerGasPrice 176 } 177 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 178 179 return eth, nil 180 } 181 182 func makeExtraData(extra []byte) []byte { 183 if len(extra) == 0 { 184 //创建默认额外数据 185 extra, _ = rlp.EncodeToBytes([]interface{}{ 186 uint(params.VersionMajor<<16 | params.VersionMinor<<8 | params.VersionPatch), 187 "geth", 188 runtime.Version(), 189 runtime.GOOS, 190 }) 191 } 192 if uint64(len(extra)) > params.MaximumExtraDataSize { 193 log.Warn("Miner extra data exceed limit", "extra", hexutil.Bytes(extra), "limit", params.MaximumExtraDataSize) 194 extra = nil 195 } 196 return extra 197 } 198 199 //createdb创建链数据库。 200 func CreateDB(ctx *node.ServiceContext, config *Config, name string) (ethdb.Database, error) { 201 db, err := ctx.OpenDatabase(name, config.DatabaseCache, config.DatabaseHandles) 202 if err != nil { 203 return nil, err 204 } 205 if db, ok := db.(*ethdb.LDBDatabase); ok { 206 db.Meter("eth/db/chaindata/") 207 } 208 return db, nil 209 } 210 211 //API返回以太坊包提供的RPC服务集合。 212 //注意,其中一些服务可能需要转移到其他地方。 213 func (s *Ethereum) APIs() []rpc.API { 214 apis := ethapi.GetAPIs(s.APIBackend) 215 216 //附加由共识引擎显式公开的任何API 217 apis = append(apis, s.engine.APIs(s.BlockChain())...) 218 219 //附加所有本地API并返回 220 return append(apis, []rpc.API{ 221 { 222 Namespace: "eth", 223 Version: "1.0", 224 Service: NewPublicEthereumAPI(s), 225 Public: true, 226 }, { 227 Namespace: "eth", 228 Version: "1.0", 229 Service: NewPublicMinerAPI(s), 230 Public: true, 231 }, { 232 Namespace: "eth", 233 Version: "1.0", 234 Service: downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux), 235 Public: true, 236 }, { 237 Namespace: "miner", 238 Version: "1.0", 239 Service: NewPrivateMinerAPI(s), 240 Public: false, 241 }, { 242 Namespace: "eth", 243 Version: "1.0", 244 Service: filters.NewPublicFilterAPI(s.APIBackend, false), 245 Public: true, 246 }, { 247 Namespace: "admin", 248 Version: "1.0", 249 Service: NewPrivateAdminAPI(s), 250 }, { 251 Namespace: "debug", 252 Version: "1.0", 253 Service: NewPublicDebugAPI(s), 254 Public: true, 255 }, { 256 Namespace: "debug", 257 Version: "1.0", 258 Service: NewPrivateDebugAPI(s.chainConfig, s), 259 }, { 260 Namespace: "net", 261 Version: "1.0", 262 Service: s.netRPCService, 263 Public: true, 264 }, 265 }...) 266 } 267 268 func (s *Ethereum) ResetWithGenesisBlock(gb *types.Block) { 269 s.blockchain.ResetWithGenesisBlock(gb) 270 } 271 272 func (s *Ethereum) Validator() (validator common.Address, err error) { 273 s.lock.RLock() 274 validator = s.validator 275 s.lock.RUnlock() 276 277 if validator != (common.Address{}) { 278 return validator, nil 279 } 280 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 281 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 282 return accounts[0].Address, nil 283 } 284 } 285 return common.Address{}, fmt.Errorf("validator address must be explicitly specified") 286 } 287 288 //通过管理接口或来自cli标志的包装器在js控制台中设置 289 func (self *Ethereum) SetValidator(validator common.Address) { 290 self.lock.Lock() 291 self.validator = validator 292 self.lock.Unlock() 293 } 294 295 func (s *Ethereum) Coinbase() (eb common.Address, err error) { 296 s.lock.RLock() 297 coinbase := s.coinbase 298 s.lock.RUnlock() 299 300 if coinbase != (common.Address{}) { 301 return coinbase, nil 302 } 303 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 304 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 305 return accounts[0].Address, nil 306 } 307 } 308 return common.Address{}, fmt.Errorf("coinbase address must be explicitly specified") 309 } 310 311 312 //通过管理接口或来自cli标志的包装器在js控制台中设置 313 func (self *Ethereum) SetCoinbase(coinbase common.Address) { 314 self.lock.Lock() 315 self.coinbase = coinbase 316 self.lock.Unlock() 317 318 self.miner.SetCoinbase(coinbase) 319 } 320 321 func (s *Ethereum) StartMining(local bool) error { 322 validator, err := s.Validator() 323 if err != nil { 324 log.Error("Cannot start mining without validator", "err", err) 325 return fmt.Errorf("validator missing: %v", err) 326 } 327 cb, err := s.Coinbase() 328 if err != nil { 329 log.Error("Cannot start mining without coinbase", "err", err) 330 return fmt.Errorf("coinbase missing: %v", err) 331 } 332 333 if dpos, ok := s.engine.(*dpos.Dpos); ok { 334 wallet, err := s.accountManager.Find(accounts.Account{Address: validator}) 335 if wallet == nil || err != nil { 336 log.Error("Coinbase account unavailable locally", "err", err) 337 return fmt.Errorf("signer missing: %v", err) 338 } 339 dpos.Authorize(validator, wallet.SignHash) 340 } 341 if local { 342 //如果启动了本地(CPU)挖掘,我们可以禁用事务拒绝 343 //用于加快同步时间的机制。在Mainnet上的CPU挖掘是荒谬的 344 //所以没有人会碰到这个路径,而在CPU挖掘上标记同步完成。 345 //也将确保私有网络以单矿工模式工作。 346 atomic.StoreUint32(&s.protocolManager.acceptTxs, 1) 347 } 348 bi := s.chainConfig.Dpos.BlockInterval 349 fmt.Println(bi) 350 go s.miner.Start(cb,bi) 351 352 return nil 353 } 354 355 func (s *Ethereum) StopMining() { s.miner.Stop() } 356 func (s *Ethereum) IsMining() bool { return s.miner.Mining() } 357 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 358 359 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 360 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 361 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 362 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 363 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 364 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 365 func (s *Ethereum) IsListening() bool { return true } //总是倾听 366 func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } 367 func (s *Ethereum) NetVersion() uint64 { return s.networkID } 368 func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } 369 370 //协议实现node.service,返回所有当前配置的 371 //要启动的网络协议。 372 func (s *Ethereum) Protocols() []p2p.Protocol { 373 if s.lesServer == nil { 374 return s.protocolManager.SubProtocols 375 } 376 return append(s.protocolManager.SubProtocols, s.lesServer.Protocols()...) 377 } 378 379 //start实现node.service,启动 380 //以太坊协议实现。 381 func (s *Ethereum) Start(srvr *p2p.Server) error { 382 //启动为Goroutines提供服务的Bloom钻头 383 s.startBloomHandlers() 384 385 //启动RPC服务 386 s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion()) 387 388 //根据服务器限制计算最大对等数 389 maxPeers := srvr.MaxPeers 390 if s.config.LightServ > 0 { 391 if s.config.LightPeers >= srvr.MaxPeers { 392 return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, srvr.MaxPeers) 393 } 394 maxPeers -= s.config.LightPeers 395 } 396 //如果需要,启动网络层和轻型服务器 397 s.protocolManager.Start(maxPeers) 398 if s.lesServer != nil { 399 s.lesServer.Start(srvr) 400 } 401 return nil 402 } 403 404 //停止实现node.service,终止由 405 //以太坊协议。 406 func (s *Ethereum) Stop() error { 407 s.bloomIndexer.Close() 408 s.blockchain.Stop() 409 s.engine.Close() 410 s.protocolManager.Stop() 411 if s.lesServer != nil { 412 s.lesServer.Stop() 413 } 414 s.txPool.Stop() 415 s.miner.Stop() 416 s.eventMux.Stop() 417 418 s.chainDb.Close() 419 close(s.shutdownChan) 420 return nil 421 } 422