github.com/dominant-strategies/go-quai@v0.28.2/eth/api_backend.go (about) 1 // Copyright 2015 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 18 19 import ( 20 "context" 21 "errors" 22 "math/big" 23 24 quai "github.com/dominant-strategies/go-quai" 25 26 "github.com/dominant-strategies/go-quai/common" 27 "github.com/dominant-strategies/go-quai/consensus" 28 "github.com/dominant-strategies/go-quai/core" 29 "github.com/dominant-strategies/go-quai/core/bloombits" 30 "github.com/dominant-strategies/go-quai/core/rawdb" 31 "github.com/dominant-strategies/go-quai/core/state" 32 "github.com/dominant-strategies/go-quai/core/types" 33 "github.com/dominant-strategies/go-quai/core/vm" 34 "github.com/dominant-strategies/go-quai/eth/downloader" 35 "github.com/dominant-strategies/go-quai/eth/gasprice" 36 "github.com/dominant-strategies/go-quai/ethdb" 37 "github.com/dominant-strategies/go-quai/event" 38 "github.com/dominant-strategies/go-quai/params" 39 "github.com/dominant-strategies/go-quai/rpc" 40 ) 41 42 // QuaiAPIBackend implements quaiapi.Backend for full nodes 43 type QuaiAPIBackend struct { 44 extRPCEnabled bool 45 eth *Quai 46 gpo *gasprice.Oracle 47 } 48 49 // ChainConfig returns the active chain configuration. 50 func (b *QuaiAPIBackend) ChainConfig() *params.ChainConfig { 51 return b.eth.core.Config() 52 } 53 54 func (b *QuaiAPIBackend) TxPool() *core.TxPool { 55 nodeCtx := common.NodeLocation.Context() 56 if nodeCtx != common.ZONE_CTX { 57 return nil 58 } 59 return b.eth.core.TxPool() 60 } 61 62 func (b *QuaiAPIBackend) CurrentBlock() *types.Block { 63 return b.eth.core.CurrentBlock() 64 } 65 66 // CurrentLogEntropy returns the logarithm of the total entropy reduction since genesis for our current head block 67 func (b *QuaiAPIBackend) CurrentLogEntropy() *big.Int { 68 return b.eth.core.CurrentLogEntropy() 69 } 70 71 // TotalLogS returns the total entropy reduction if the chain since genesis to the given header 72 func (b *QuaiAPIBackend) TotalLogS(header *types.Header) *big.Int { 73 return b.eth.core.TotalLogS(header) 74 } 75 76 // CalcOrder returns the order of the block within the hierarchy of chains 77 func (b *QuaiAPIBackend) CalcOrder(header *types.Header) (*big.Int, int, error) { 78 return b.eth.core.CalcOrder(header) 79 } 80 81 func (b *QuaiAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 82 // Pending block is only known by the miner 83 if number == rpc.PendingBlockNumber { 84 block := b.eth.core.PendingBlock() 85 return block.Header(), nil 86 } 87 // Otherwise resolve and return the block 88 if number == rpc.LatestBlockNumber { 89 return b.eth.core.CurrentBlock().Header(), nil 90 } 91 return b.eth.core.GetHeaderByNumber(uint64(number)), nil 92 } 93 94 func (b *QuaiAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) { 95 if blockNr, ok := blockNrOrHash.Number(); ok { 96 return b.HeaderByNumber(ctx, blockNr) 97 } 98 if hash, ok := blockNrOrHash.Hash(); ok { 99 header := b.eth.core.GetHeaderByHash(hash) 100 if header == nil { 101 return nil, errors.New("header for hash not found") 102 } 103 if blockNrOrHash.RequireCanonical && b.eth.core.GetCanonicalHash(header.Number().Uint64()) != hash { 104 return nil, errors.New("hash is not currently canonical") 105 } 106 return header, nil 107 } 108 return nil, errors.New("invalid arguments; neither block nor hash specified") 109 } 110 111 func (b *QuaiAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) { 112 return b.eth.core.GetHeaderByHash(hash), nil 113 } 114 115 func (b *QuaiAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 116 // Pending block is only known by the miner 117 if number == rpc.PendingBlockNumber { 118 block := b.eth.core.PendingBlock() 119 return block, nil 120 } 121 // Otherwise resolve and return the block 122 if number == rpc.LatestBlockNumber { 123 number = rpc.BlockNumber(b.eth.core.CurrentHeader().NumberU64()) 124 } 125 block := b.eth.core.GetBlockByNumber(uint64(number)) 126 if block != nil { 127 return block, nil 128 } 129 return nil, errors.New("block is nil api backend") 130 } 131 132 func (b *QuaiAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) { 133 return b.eth.core.GetBlockByHash(hash), nil 134 } 135 136 func (b *QuaiAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) { 137 if blockNr, ok := blockNrOrHash.Number(); ok { 138 return b.BlockByNumber(ctx, blockNr) 139 } 140 if hash, ok := blockNrOrHash.Hash(); ok { 141 header := b.eth.core.GetHeaderByHash(hash) 142 if header == nil { 143 return nil, errors.New("header for hash not found") 144 } 145 if blockNrOrHash.RequireCanonical && b.eth.core.GetCanonicalHash(header.Number().Uint64()) != hash { 146 return nil, errors.New("hash is not currently canonical") 147 } 148 block := b.eth.core.GetBlock(hash, header.Number().Uint64()) 149 if block == nil { 150 return nil, errors.New("header found, but block body is missing") 151 } 152 return block, nil 153 } 154 return nil, errors.New("invalid arguments; neither block nor hash specified") 155 } 156 157 func (b *QuaiAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { 158 return b.eth.core.PendingBlockAndReceipts() 159 } 160 161 func (b *QuaiAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { 162 nodeCtx := common.NodeLocation.Context() 163 if nodeCtx != common.ZONE_CTX { 164 return nil, nil, errors.New("stateAndHeaderByNumber can only be called in zone chain") 165 } 166 // Pending state is only known by the miner 167 if number == rpc.PendingBlockNumber { 168 block := b.eth.core.Pending() 169 return &state.StateDB{}, block.Header(), nil 170 } 171 // Otherwise resolve the block number and return its state 172 header, err := b.HeaderByNumber(ctx, number) 173 if err != nil { 174 return nil, nil, err 175 } 176 if header == nil { 177 return nil, nil, errors.New("header not found") 178 } 179 stateDb, err := b.eth.Core().StateAt(header.Root()) 180 return stateDb, header, err 181 } 182 183 func (b *QuaiAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { 184 nodeCtx := common.NodeLocation.Context() 185 if nodeCtx != common.ZONE_CTX { 186 return nil, nil, errors.New("stateAndHeaderByNumberOrHash can only be called in zone chain") 187 } 188 if blockNr, ok := blockNrOrHash.Number(); ok { 189 return b.StateAndHeaderByNumber(ctx, blockNr) 190 } 191 if hash, ok := blockNrOrHash.Hash(); ok { 192 header, err := b.HeaderByHash(ctx, hash) 193 if err != nil { 194 return nil, nil, err 195 } 196 if header == nil { 197 return nil, nil, errors.New("header for hash not found") 198 } 199 if blockNrOrHash.RequireCanonical && b.eth.core.GetCanonicalHash(header.Number().Uint64()) != hash { 200 return nil, nil, errors.New("hash is not currently canonical") 201 } 202 stateDb, err := b.eth.Core().StateAt(header.Root()) 203 return stateDb, header, err 204 } 205 return nil, nil, errors.New("invalid arguments; neither block nor hash specified") 206 } 207 208 func (b *QuaiAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 209 nodeCtx := common.NodeLocation.Context() 210 if nodeCtx != common.ZONE_CTX { 211 return nil, errors.New("getReceipts can only be called in zone chain") 212 } 213 return b.eth.core.GetReceiptsByHash(hash), nil 214 } 215 216 // GetBloom returns the bloom for the given block hash 217 func (b *QuaiAPIBackend) GetBloom(hash common.Hash) (*types.Bloom, error) { 218 nodeCtx := common.NodeLocation.Context() 219 if nodeCtx != common.ZONE_CTX { 220 return nil, errors.New("getBloom can only be called in zone chain") 221 } 222 return b.eth.core.Slice().HeaderChain().GetBloom(hash) 223 } 224 225 func (b *QuaiAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) { 226 nodeCtx := common.NodeLocation.Context() 227 if nodeCtx != common.ZONE_CTX { 228 return nil, errors.New("getLogs can only be called in zone chain") 229 } 230 receipts := b.eth.core.GetReceiptsByHash(hash) 231 if receipts == nil { 232 return nil, nil 233 } 234 logs := make([][]*types.Log, len(receipts)) 235 for i, receipt := range receipts { 236 logs[i] = receipt.Logs 237 } 238 return logs, nil 239 } 240 241 func (b *QuaiAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { 242 vmError := func() error { return nil } 243 nodeCtx := common.NodeLocation.Context() 244 if nodeCtx != common.ZONE_CTX { 245 return nil, vmError, errors.New("getEvm can only be called in zone chain") 246 } 247 if vmConfig == nil { 248 vmConfig = b.eth.core.GetVMConfig() 249 } 250 txContext := core.NewEVMTxContext(msg) 251 context := core.NewEVMBlockContext(header, b.eth.Core(), nil) 252 return vm.NewEVM(context, txContext, state, b.eth.core.Config(), *vmConfig), vmError, nil 253 } 254 255 func (b *QuaiAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { 256 nodeCtx := common.NodeLocation.Context() 257 if nodeCtx != common.ZONE_CTX { 258 return nil 259 } 260 return b.eth.Core().SubscribeRemovedLogsEvent(ch) 261 } 262 263 func (b *QuaiAPIBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription { 264 nodeCtx := common.NodeLocation.Context() 265 if nodeCtx != common.ZONE_CTX { 266 return nil 267 } 268 return b.eth.core.SubscribePendingLogs(ch) 269 } 270 271 func (b *QuaiAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { 272 return b.eth.Core().SubscribeChainEvent(ch) 273 } 274 275 func (b *QuaiAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 276 return b.eth.Core().SubscribeChainHeadEvent(ch) 277 } 278 279 func (b *QuaiAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription { 280 return b.eth.Core().SubscribeChainSideEvent(ch) 281 } 282 283 func (b *QuaiAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { 284 nodeCtx := common.NodeLocation.Context() 285 if nodeCtx != common.ZONE_CTX { 286 return nil 287 } 288 return b.eth.Core().SubscribeLogsEvent(ch) 289 } 290 291 func (b *QuaiAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { 292 nodeCtx := common.NodeLocation.Context() 293 if nodeCtx != common.ZONE_CTX { 294 return errors.New("sendTx can only be called in zone chain") 295 } 296 return b.eth.Core().AddLocal(signedTx) 297 } 298 299 func (b *QuaiAPIBackend) GetPoolTransactions() (types.Transactions, error) { 300 nodeCtx := common.NodeLocation.Context() 301 if nodeCtx != common.ZONE_CTX { 302 return nil, errors.New("getPoolTransactions can only be called in zone chain") 303 } 304 pending, err := b.eth.core.TxPoolPending(false) 305 if err != nil { 306 return nil, err 307 } 308 var txs types.Transactions 309 for _, batch := range pending { 310 txs = append(txs, batch...) 311 } 312 return txs, nil 313 } 314 315 func (b *QuaiAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction { 316 nodeCtx := common.NodeLocation.Context() 317 if nodeCtx != common.ZONE_CTX { 318 return nil 319 } 320 return b.eth.core.Get(hash) 321 } 322 323 func (b *QuaiAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) { 324 nodeCtx := common.NodeLocation.Context() 325 if nodeCtx != common.ZONE_CTX { 326 return nil, common.Hash{}, 0, 0, errors.New("getTransaction can only be called in zone chain") 327 } 328 tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash) 329 return tx, blockHash, blockNumber, index, nil 330 } 331 332 func (b *QuaiAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) { 333 nodeCtx := common.NodeLocation.Context() 334 if nodeCtx != common.ZONE_CTX { 335 return 0, errors.New("getPoolNonce can only be called in zone chain") 336 } 337 return b.eth.core.Nonce(addr), nil 338 } 339 340 func (b *QuaiAPIBackend) Stats() (pending int, queued int) { 341 return b.eth.core.Stats() 342 } 343 344 func (b *QuaiAPIBackend) TxPoolContent() (map[common.InternalAddress]types.Transactions, map[common.InternalAddress]types.Transactions) { 345 nodeCtx := common.NodeLocation.Context() 346 if nodeCtx != common.ZONE_CTX { 347 return nil, nil 348 } 349 return b.eth.core.Content() 350 } 351 352 func (b *QuaiAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) { 353 nodeCtx := common.NodeLocation.Context() 354 if nodeCtx != common.ZONE_CTX { 355 return nil, nil 356 } 357 return b.eth.core.ContentFrom(addr) 358 } 359 360 func (b *QuaiAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { 361 nodeCtx := common.NodeLocation.Context() 362 if nodeCtx != common.ZONE_CTX { 363 return nil 364 } 365 return b.eth.core.SubscribeNewTxsEvent(ch) 366 } 367 368 func (b *QuaiAPIBackend) Downloader() *downloader.Downloader { 369 return b.eth.Downloader() 370 } 371 372 func (b *QuaiAPIBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 373 nodeCtx := common.NodeLocation.Context() 374 if nodeCtx != common.ZONE_CTX { 375 return nil, errors.New("suggestTipCap can only be called in zone chain") 376 } 377 return b.gpo.SuggestTipCap(ctx) 378 } 379 380 func (b *QuaiAPIBackend) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (firstBlock *big.Int, reward [][]*big.Int, baseFee []*big.Int, gasUsedRatio []float64, err error) { 381 return b.gpo.FeeHistory(ctx, blockCount, lastBlock, rewardPercentiles) 382 } 383 384 func (b *QuaiAPIBackend) ChainDb() ethdb.Database { 385 return b.eth.ChainDb() 386 } 387 388 func (b *QuaiAPIBackend) EventMux() *event.TypeMux { 389 return b.eth.EventMux() 390 } 391 392 func (b *QuaiAPIBackend) ExtRPCEnabled() bool { 393 return b.extRPCEnabled 394 } 395 396 func (b *QuaiAPIBackend) RPCGasCap() uint64 { 397 nodeCtx := common.NodeLocation.Context() 398 if nodeCtx != common.ZONE_CTX { 399 return 0 400 } 401 return b.eth.config.RPCGasCap 402 } 403 404 func (b *QuaiAPIBackend) RPCTxFeeCap() float64 { 405 nodeCtx := common.NodeLocation.Context() 406 if nodeCtx != common.ZONE_CTX { 407 return 0 408 } 409 return b.eth.config.RPCTxFeeCap 410 } 411 412 func (b *QuaiAPIBackend) BloomStatus() (uint64, uint64) { 413 sections, _, _ := b.eth.bloomIndexer.Sections() 414 return params.BloomBitsBlocks, sections 415 } 416 417 func (b *QuaiAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) { 418 for i := 0; i < bloomFilterThreads; i++ { 419 go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests) 420 } 421 } 422 423 func (b *QuaiAPIBackend) Engine() consensus.Engine { 424 return b.eth.engine 425 } 426 427 func (b *QuaiAPIBackend) CurrentHeader() *types.Header { 428 return b.eth.core.CurrentHeader() 429 } 430 431 func (b *QuaiAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive bool) (*state.StateDB, error) { 432 nodeCtx := common.NodeLocation.Context() 433 if nodeCtx != common.ZONE_CTX { 434 return nil, errors.New("stateAtBlock can only be called in zone chain") 435 } 436 return b.eth.core.StateAtBlock(block, reexec, base, checkLive) 437 } 438 439 func (b *QuaiAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error) { 440 nodeCtx := common.NodeLocation.Context() 441 if nodeCtx != common.ZONE_CTX { 442 return nil, vm.BlockContext{}, nil, errors.New("stateAtTransaction can only be called in zone chain") 443 } 444 return b.eth.core.StateAtTransaction(block, txIndex, reexec) 445 } 446 447 func (b *QuaiAPIBackend) SyncProgress() quai.SyncProgress { 448 return b.eth.Downloader().Progress() 449 } 450 451 func (b *QuaiAPIBackend) Append(header *types.Header, manifest types.BlockManifest, domPendingHeader *types.Header, domTerminus common.Hash, domOrigin bool, newInboundEtxs types.Transactions) (types.Transactions, bool, bool, error) { 452 return b.eth.core.Append(header, manifest, domPendingHeader, domTerminus, domOrigin, newInboundEtxs) 453 } 454 455 func (b *QuaiAPIBackend) DownloadBlocksInManifest(hash common.Hash, manifest types.BlockManifest, entropy *big.Int) { 456 b.eth.core.DownloadBlocksInManifest(hash, manifest, entropy) 457 } 458 459 func (b *QuaiAPIBackend) ConstructLocalMinedBlock(header *types.Header) (*types.Block, error) { 460 return b.eth.core.ConstructLocalMinedBlock(header) 461 } 462 463 func (b *QuaiAPIBackend) InsertBlock(ctx context.Context, block *types.Block) (int, error) { 464 return b.eth.core.InsertChain([]*types.Block{block}) 465 } 466 467 func (b *QuaiAPIBackend) WriteBlock(block *types.Block) { 468 b.eth.core.WriteBlock(block) 469 } 470 471 func (b *QuaiAPIBackend) PendingBlock() *types.Block { 472 return b.eth.core.PendingBlock() 473 } 474 475 func (b *QuaiAPIBackend) SubRelayPendingHeader(pendingHeader types.PendingHeader, newEntropy *big.Int, location common.Location, subReorg bool, order int) { 476 b.eth.core.SubRelayPendingHeader(pendingHeader, newEntropy, location, subReorg, order) 477 } 478 479 func (b *QuaiAPIBackend) UpdateDom(oldTerminus common.Hash, pendingHeader types.PendingHeader, location common.Location) { 480 b.eth.core.UpdateDom(oldTerminus, pendingHeader, location) 481 } 482 483 func (b *QuaiAPIBackend) RequestDomToAppendOrFetch(hash common.Hash, entropy *big.Int, order int) { 484 b.eth.core.RequestDomToAppendOrFetch(hash, entropy, order) 485 } 486 487 func (b *QuaiAPIBackend) ProcessingState() bool { 488 return b.eth.core.ProcessingState() 489 } 490 491 func (b *QuaiAPIBackend) NewGenesisPendingHeader(pendingHeader *types.Header) { 492 b.eth.core.NewGenesisPendigHeader(pendingHeader) 493 } 494 495 func (b *QuaiAPIBackend) GetPendingHeader() (*types.Header, error) { 496 return b.eth.core.GetPendingHeader() 497 } 498 499 func (b *QuaiAPIBackend) GetManifest(blockHash common.Hash) (types.BlockManifest, error) { 500 return b.eth.core.GetManifest(blockHash) 501 } 502 503 func (b *QuaiAPIBackend) GetSubManifest(slice common.Location, blockHash common.Hash) (types.BlockManifest, error) { 504 return b.eth.core.GetSubManifest(slice, blockHash) 505 } 506 507 func (b *QuaiAPIBackend) AddPendingEtxs(pEtxs types.PendingEtxs) error { 508 return b.eth.core.AddPendingEtxs(pEtxs) 509 } 510 511 func (b *QuaiAPIBackend) AddPendingEtxsRollup(pEtxsRollup types.PendingEtxsRollup) error { 512 return b.eth.core.AddPendingEtxsRollup(pEtxsRollup) 513 } 514 515 func (b *QuaiAPIBackend) SubscribePendingHeaderEvent(ch chan<- *types.Header) event.Subscription { 516 return b.eth.core.SubscribePendingHeader(ch) 517 } 518 519 func (b *QuaiAPIBackend) GenerateRecoveryPendingHeader(pendingHeader *types.Header, checkpointHashes types.Termini) error { 520 return b.eth.core.GenerateRecoveryPendingHeader(pendingHeader, checkpointHashes) 521 } 522 523 func (b *QuaiAPIBackend) GetPendingEtxsRollupFromSub(hash common.Hash, location common.Location) (types.PendingEtxsRollup, error) { 524 return b.eth.core.GetPendingEtxsRollupFromSub(hash, location) 525 } 526 527 func (b *QuaiAPIBackend) GetPendingEtxsFromSub(hash common.Hash, location common.Location) (types.PendingEtxs, error) { 528 return b.eth.core.GetPendingEtxsFromSub(hash, location) 529 } 530 531 func (b *QuaiAPIBackend) SetSyncTarget(header *types.Header) { 532 b.eth.core.SetSyncTarget(header) 533 }