gitlab.com/flarenetwork/coreth@v0.1.1/eth/backend.go (about) 1 // (c) 2019-2020, Ava Labs, Inc. 2 // 3 // This file is a derived work, based on the go-ethereum library whose original 4 // notices appear below. 5 // 6 // It is distributed under a license compatible with the licensing terms of the 7 // original code from which it is derived. 8 // 9 // Much love to the original authors for their work. 10 // ********** 11 // Copyright 2014 The go-ethereum Authors 12 // This file is part of the go-ethereum library. 13 // 14 // The go-ethereum library is free software: you can redistribute it and/or modify 15 // it under the terms of the GNU Lesser General Public License as published by 16 // the Free Software Foundation, either version 3 of the License, or 17 // (at your option) any later version. 18 // 19 // The go-ethereum library is distributed in the hope that it will be useful, 20 // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 // GNU Lesser General Public License for more details. 23 // 24 // You should have received a copy of the GNU Lesser General Public License 25 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 26 27 // Package eth implements the Ethereum protocol. 28 package eth 29 30 import ( 31 "errors" 32 "fmt" 33 "sync" 34 "time" 35 36 "github.com/ethereum/go-ethereum/common" 37 "github.com/ethereum/go-ethereum/eth/downloader" 38 "github.com/ethereum/go-ethereum/ethdb" 39 "github.com/ethereum/go-ethereum/event" 40 "github.com/ethereum/go-ethereum/log" 41 "gitlab.com/flarenetwork/coreth/accounts" 42 "gitlab.com/flarenetwork/coreth/consensus" 43 "gitlab.com/flarenetwork/coreth/consensus/dummy" 44 "gitlab.com/flarenetwork/coreth/core" 45 "gitlab.com/flarenetwork/coreth/core/bloombits" 46 "gitlab.com/flarenetwork/coreth/core/rawdb" 47 "gitlab.com/flarenetwork/coreth/core/types" 48 "gitlab.com/flarenetwork/coreth/core/vm" 49 "gitlab.com/flarenetwork/coreth/eth/ethconfig" 50 "gitlab.com/flarenetwork/coreth/eth/filters" 51 "gitlab.com/flarenetwork/coreth/eth/gasprice" 52 "gitlab.com/flarenetwork/coreth/eth/tracers" 53 "gitlab.com/flarenetwork/coreth/internal/ethapi" 54 "gitlab.com/flarenetwork/coreth/miner" 55 "gitlab.com/flarenetwork/coreth/node" 56 "gitlab.com/flarenetwork/coreth/params" 57 "gitlab.com/flarenetwork/coreth/rpc" 58 ) 59 60 // Config contains the configuration options of the ETH protocol. 61 // Deprecated: use ethconfig.Config instead. 62 type Config = ethconfig.Config 63 64 var ( 65 DefaultSettings Settings = Settings{MaxBlocksPerRequest: 2000} 66 ) 67 68 type Settings struct { 69 MaxBlocksPerRequest int64 // Maximum number of blocks to serve per getLogs request 70 } 71 72 // Ethereum implements the Ethereum full node service. 73 type Ethereum struct { 74 config *Config 75 76 // Handlers 77 txPool *core.TxPool 78 blockchain *core.BlockChain 79 80 // DB interfaces 81 chainDb ethdb.Database // Block chain database 82 83 eventMux *event.TypeMux 84 engine consensus.Engine 85 accountManager *accounts.Manager 86 87 bloomRequests chan chan *bloombits.Retrieval // Channel receiving bloom data retrieval requests 88 bloomIndexer *core.ChainIndexer // Bloom indexer operating during block imports 89 closeBloomHandler chan struct{} 90 91 APIBackend *EthAPIBackend 92 93 miner *miner.Miner 94 etherbase common.Address 95 96 networkID uint64 97 netRPCService *ethapi.PublicNetAPI 98 99 lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) 100 101 settings Settings // Settings for Ethereum API 102 } 103 104 // New creates a new Ethereum object (including the 105 // initialisation of the common Ethereum object) 106 func New(stack *node.Node, config *Config, 107 cb *dummy.ConsensusCallbacks, 108 chainDb ethdb.Database, 109 settings Settings, 110 lastAcceptedHash common.Hash, 111 ) (*Ethereum, error) { 112 if chainDb == nil { 113 return nil, errors.New("chainDb cannot be nil") 114 } 115 if !config.Pruning && config.TrieDirtyCache > 0 { 116 // If snapshots are enabled, allocate 2/5 of the TrieDirtyCache memory cap to the snapshot cache 117 if config.SnapshotCache > 0 { 118 config.TrieCleanCache += config.TrieDirtyCache * 3 / 5 119 config.SnapshotCache += config.TrieDirtyCache * 2 / 5 120 } else { 121 // If snapshots are disabled, the TrieDirtyCache will be written through to the clean cache 122 // so move the cache allocation from the dirty cache to the clean cache 123 config.TrieCleanCache += config.TrieDirtyCache 124 config.TrieDirtyCache = 0 125 } 126 } 127 log.Info("Allocated trie memory caches", "clean", common.StorageSize(config.TrieCleanCache)*1024*1024, "dirty", common.StorageSize(config.TrieDirtyCache)*1024*1024) 128 129 chainConfig, genesisErr := core.SetupGenesisBlock(chainDb, config.Genesis) 130 if genesisErr != nil { 131 return nil, genesisErr 132 } 133 log.Info("Initialised chain configuration", "config", chainConfig) 134 135 // FIXME RecoverPruning once that package is migrated over 136 // if err := pruner.RecoverPruning(stack.ResolvePath(""), chainDb, stack.ResolvePath(config.TrieCleanCacheJournal)); err != nil { 137 // log.Error("Failed to recover state", "error", err) 138 // } 139 eth := &Ethereum{ 140 config: config, 141 chainDb: chainDb, 142 eventMux: stack.EventMux(), 143 accountManager: stack.AccountManager(), 144 engine: dummy.NewDummyEngine(cb), 145 closeBloomHandler: make(chan struct{}), 146 networkID: config.NetworkId, 147 etherbase: config.Miner.Etherbase, 148 bloomRequests: make(chan chan *bloombits.Retrieval), 149 bloomIndexer: core.NewBloomIndexer(chainDb, params.BloomBitsBlocks, params.BloomConfirms), 150 settings: settings, 151 } 152 153 bcVersion := rawdb.ReadDatabaseVersion(chainDb) 154 var dbVer = "<nil>" 155 if bcVersion != nil { 156 dbVer = fmt.Sprintf("%d", *bcVersion) 157 } 158 log.Info("Initialising Ethereum protocol", "network", config.NetworkId, "dbversion", dbVer) 159 160 if !config.SkipBcVersionCheck { 161 if bcVersion != nil && *bcVersion > core.BlockChainVersion { 162 return nil, fmt.Errorf("database version is v%d, Coreth %s only supports v%d", *bcVersion, params.VersionWithMeta, core.BlockChainVersion) 163 } else if bcVersion == nil || *bcVersion < core.BlockChainVersion { 164 log.Warn("Upgrade blockchain database version", "from", dbVer, "to", core.BlockChainVersion) 165 rawdb.WriteDatabaseVersion(chainDb, core.BlockChainVersion) 166 } 167 } 168 var ( 169 vmConfig = vm.Config{ 170 EnablePreimageRecording: config.EnablePreimageRecording, 171 AllowUnfinalizedQueries: config.AllowUnfinalizedQueries, 172 } 173 cacheConfig = &core.CacheConfig{ 174 TrieCleanLimit: config.TrieCleanCache, 175 TrieDirtyLimit: config.TrieDirtyCache, 176 Pruning: config.Pruning, 177 SnapshotLimit: config.SnapshotCache, 178 SnapshotAsync: config.SnapshotAsync, 179 SnapshotVerify: config.SnapshotVerify, 180 Preimages: config.Preimages, 181 } 182 ) 183 var err error 184 eth.blockchain, err = core.NewBlockChain(chainDb, cacheConfig, chainConfig, eth.engine, vmConfig, lastAcceptedHash) 185 if err != nil { 186 return nil, err 187 } 188 eth.bloomIndexer.Start(eth.blockchain) 189 190 // Original code (requires disk): 191 // if config.TxPool.Journal != "" { 192 // config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal) 193 // } 194 config.TxPool.Journal = "" 195 eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain) 196 197 eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine) 198 199 // FIXME use node config to pass in config param on whether or not to allow unprotected 200 // currently defaults to false. 201 allowUnprotectedTxs := false 202 eth.APIBackend = &EthAPIBackend{stack.Config().ExtRPCEnabled(), false, eth, nil} 203 if allowUnprotectedTxs { 204 log.Info("Unprotected transactions allowed") 205 } 206 gpoParams := config.GPO 207 eth.APIBackend.gpo = gasprice.NewOracle(eth.APIBackend, gpoParams) 208 209 if err != nil { 210 return nil, err 211 } 212 213 // Start the RPC service 214 eth.netRPCService = ethapi.NewPublicNetAPI(eth.NetVersion()) 215 216 // Register the backend on the node 217 stack.RegisterAPIs(eth.APIs()) 218 219 return eth, nil 220 } 221 222 // APIs return the collection of RPC services the ethereum package offers. 223 // NOTE, some of these services probably need to be moved to somewhere else. 224 func (s *Ethereum) APIs() []rpc.API { 225 apis := ethapi.GetAPIs(s.APIBackend) 226 227 // Append tracing APIs 228 apis = append(apis, tracers.APIs(s.APIBackend)...) 229 230 // Append any APIs exposed explicitly by the consensus engine 231 apis = append(apis, s.engine.APIs(s.BlockChain())...) 232 233 // Append all the local APIs and return 234 return append(apis, []rpc.API{ 235 { 236 Namespace: "eth", 237 Version: "1.0", 238 Service: NewPublicEthereumAPI(s), 239 Public: true, 240 }, { 241 Namespace: "eth", 242 Version: "1.0", 243 Service: filters.NewPublicFilterAPI(s.APIBackend, false, 5*time.Minute), 244 Public: true, 245 }, { 246 Namespace: "admin", 247 Version: "1.0", 248 Service: NewPrivateAdminAPI(s), 249 }, { 250 Namespace: "debug", 251 Version: "1.0", 252 Service: NewPublicDebugAPI(s), 253 Public: true, 254 }, { 255 Namespace: "debug", 256 Version: "1.0", 257 Service: NewPrivateDebugAPI(s), 258 }, { 259 Namespace: "net", 260 Version: "1.0", 261 Service: s.netRPCService, 262 Public: true, 263 }, 264 }...) 265 } 266 267 func (s *Ethereum) Etherbase() (eb common.Address, err error) { 268 s.lock.RLock() 269 etherbase := s.etherbase 270 s.lock.RUnlock() 271 272 if etherbase != (common.Address{}) { 273 return etherbase, nil 274 } 275 if wallets := s.AccountManager().Wallets(); len(wallets) > 0 { 276 if accounts := wallets[0].Accounts(); len(accounts) > 0 { 277 etherbase := accounts[0].Address 278 279 s.lock.Lock() 280 s.etherbase = etherbase 281 s.lock.Unlock() 282 283 log.Info("Etherbase automatically configured", "address", etherbase) 284 return etherbase, nil 285 } 286 } 287 return common.Address{}, fmt.Errorf("etherbase must be explicitly specified") 288 } 289 290 // SetEtherbase sets the mining reward address. 291 func (s *Ethereum) SetEtherbase(etherbase common.Address) { 292 s.lock.Lock() 293 s.etherbase = etherbase 294 s.lock.Unlock() 295 296 s.miner.SetEtherbase(etherbase) 297 } 298 299 func (s *Ethereum) Miner() *miner.Miner { return s.miner } 300 301 func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager } 302 func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain } 303 func (s *Ethereum) TxPool() *core.TxPool { return s.txPool } 304 func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux } 305 func (s *Ethereum) Engine() consensus.Engine { return s.engine } 306 func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb } 307 308 // FIXME remove NetVersion, IsListening, Downloader, and Synced 309 func (s *Ethereum) IsListening() bool { return true } // Always listening 310 func (s *Ethereum) NetVersion() uint64 { return s.networkID } 311 func (s *Ethereum) Downloader() *downloader.Downloader { return nil } // s.protocolManager.downloader } 312 func (s *Ethereum) Synced() bool { return true } // atomic.LoadUint32(&s.protocolManager.acceptTxs) == 1 } 313 func (s *Ethereum) ArchiveMode() bool { return !s.config.Pruning } 314 func (s *Ethereum) BloomIndexer() *core.ChainIndexer { return s.bloomIndexer } 315 316 // Start implements node.Lifecycle, starting all internal goroutines needed by the 317 // Ethereum protocol implementation. 318 func (s *Ethereum) Start() { 319 // Start the bloom bits servicing goroutines 320 s.startBloomHandlers(params.BloomBitsBlocks) 321 } 322 323 // Stop implements node.Lifecycle, terminating all internal goroutines used by the 324 // Ethereum protocol. 325 // FIXME remove error from type if this will never return an error 326 func (s *Ethereum) Stop() error { 327 s.bloomIndexer.Close() 328 close(s.closeBloomHandler) 329 s.txPool.Stop() 330 s.blockchain.Stop() 331 s.engine.Close() 332 s.chainDb.Close() 333 s.eventMux.Stop() 334 return nil 335 } 336 337 func (s *Ethereum) LastAcceptedBlock() *types.Block { 338 return s.blockchain.LastAcceptedBlock() 339 }