2020-08-01 07:39:04 +00:00
package commands
import (
"context"
2020-08-29 21:28:09 +00:00
"fmt"
2020-08-22 20:13:38 +00:00
2020-08-01 07:39:04 +00:00
"github.com/ledgerwatch/turbo-geth/common"
"github.com/ledgerwatch/turbo-geth/common/hexutil"
"github.com/ledgerwatch/turbo-geth/core"
2020-08-29 21:28:09 +00:00
"github.com/ledgerwatch/turbo-geth/core/rawdb"
2020-08-01 07:39:04 +00:00
"github.com/ledgerwatch/turbo-geth/core/types"
"github.com/ledgerwatch/turbo-geth/eth/stagedsync/stages"
"github.com/ledgerwatch/turbo-geth/ethdb"
"github.com/ledgerwatch/turbo-geth/internal/ethapi"
"github.com/ledgerwatch/turbo-geth/rpc"
)
// EthAPI is a collection of functions that are exposed in the
type EthAPI interface {
2020-08-12 13:47:59 +00:00
Coinbase ( ctx context . Context ) ( common . Address , error )
2020-08-01 07:39:04 +00:00
BlockNumber ( ctx context . Context ) ( hexutil . Uint64 , error )
GetBlockByNumber ( ctx context . Context , number rpc . BlockNumber , fullTx bool ) ( map [ string ] interface { } , error )
2020-08-22 20:13:38 +00:00
GetBlockByHash ( ctx context . Context , hash common . Hash , fullTx bool ) ( map [ string ] interface { } , error )
2020-08-12 13:47:59 +00:00
GetBalance ( ctx context . Context , address common . Address , blockNrOrHash rpc . BlockNumberOrHash ) ( * hexutil . Big , error )
2020-08-01 07:39:04 +00:00
GetTransactionReceipt ( ctx context . Context , hash common . Hash ) ( map [ string ] interface { } , error )
GetLogs ( ctx context . Context , hash common . Hash ) ( [ ] [ ] * types . Log , error )
2020-08-12 13:46:35 +00:00
Call ( ctx context . Context , args ethapi . CallArgs , blockNrOrHash rpc . BlockNumberOrHash , overrides * map [ common . Address ] ethapi . Account ) ( hexutil . Bytes , error )
2020-08-01 07:39:04 +00:00
EstimateGas ( ctx context . Context , args ethapi . CallArgs ) ( hexutil . Uint64 , error )
2020-08-11 21:09:30 +00:00
SendRawTransaction ( ctx context . Context , encodedTx hexutil . Bytes ) ( common . Hash , error )
2020-08-29 07:24:50 +00:00
Syncing ( ctx context . Context ) ( interface { } , error )
2020-08-29 21:28:09 +00:00
GetBlockTransactionCountByNumber ( ctx context . Context , blockNr rpc . BlockNumber ) ( * hexutil . Uint , error )
GetBlockTransactionCountByHash ( ctx context . Context , blockHash common . Hash ) ( * hexutil . Uint , error )
2020-08-01 07:39:04 +00:00
}
// APIImpl is implementation of the EthAPI interface based on remote Db access
type APIImpl struct {
db ethdb . KV
2020-08-12 13:47:59 +00:00
ethBackend ethdb . Backend
2020-08-01 07:39:04 +00:00
dbReader ethdb . Getter
chainContext core . ChainContext
2020-08-19 11:46:20 +00:00
GasCap uint64
2020-08-01 07:39:04 +00:00
}
// NewAPI returns APIImpl instance
2020-08-19 11:46:20 +00:00
func NewAPI ( db ethdb . KV , dbReader ethdb . Getter , eth ethdb . Backend , gascap uint64 ) * APIImpl {
2020-08-01 07:39:04 +00:00
return & APIImpl {
2020-08-19 11:46:20 +00:00
db : db ,
dbReader : dbReader ,
ethBackend : eth ,
GasCap : gascap ,
2020-08-01 07:39:04 +00:00
}
}
func ( api * APIImpl ) BlockNumber ( ctx context . Context ) ( hexutil . Uint64 , error ) {
2020-08-30 16:51:06 +00:00
execution , _ , err := stages . GetStageProgress ( api . dbReader , stages . Finish )
2020-08-01 07:39:04 +00:00
if err != nil {
return 0 , err
}
return hexutil . Uint64 ( execution ) , nil
}
2020-08-29 07:24:50 +00:00
// Syncing - we can return the progress of the very first stage as the highest block, and then the progress of the very last stage as the current block
func ( api * APIImpl ) Syncing ( ctx context . Context ) ( interface { } , error ) {
highestBlock , _ , err := stages . GetStageProgress ( api . dbReader , stages . Headers )
if err != nil {
return false , err
}
2020-08-31 05:27:35 +00:00
currentBlock , _ , err := stages . GetStageProgress ( api . dbReader , stages . Finish )
2020-08-29 07:24:50 +00:00
if err != nil {
return false , err
}
// Return not syncing if the synchronisation already completed
if currentBlock >= highestBlock {
return false , nil
}
// Otherwise gather the block sync stats
return map [ string ] hexutil . Uint64 {
"currentBlock" : hexutil . Uint64 ( currentBlock ) ,
"highestBlock" : hexutil . Uint64 ( highestBlock ) ,
} , nil
}
2020-08-29 21:28:09 +00:00
func ( api * APIImpl ) GetBlockTransactionCountByNumber ( ctx context . Context , blockNr rpc . BlockNumber ) ( * hexutil . Uint , error ) {
var blockNum uint64
if blockNr == rpc . LatestBlockNumber || blockNr == rpc . PendingBlockNumber {
var err error
blockNum , _ , err = stages . GetStageProgress ( api . dbReader , stages . Execution )
if err != nil {
return nil , fmt . Errorf ( "getting latest block number: %v" , err )
}
} else if blockNr == rpc . EarliestBlockNumber {
blockNum = 0
} else {
blockNum = uint64 ( blockNr . Int64 ( ) )
}
block := rawdb . ReadBlockByNumber ( api . dbReader , blockNum )
if block == nil {
return nil , fmt . Errorf ( "block not found: %d" , blockNum )
}
n := hexutil . Uint ( len ( block . Transactions ( ) ) )
return & n , nil
}
func ( api * APIImpl ) GetBlockTransactionCountByHash ( ctx context . Context , blockHash common . Hash ) ( * hexutil . Uint , error ) {
block := rawdb . ReadBlockByHash ( api . dbReader , blockHash )
if block == nil {
return nil , fmt . Errorf ( "block not found: %x" , blockHash )
}
n := hexutil . Uint ( len ( block . Transactions ( ) ) )
return & n , nil
}