diff --git a/core/blockchain.go b/core/blockchain.go index f886ffe4ed..a25c46a741 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1348,6 +1348,11 @@ func (bc *BlockChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []com return bc.hc.GetBlockHashesFromHash(hash, max) } +// GetBlockHashByNumber retrieves the block hash from the database by number. +func (bc *BlockChain) GetBlockHashByNumber(number uint64) common.Hash { + return bc.hc.GetBlockHashByNumber(number) +} + // GetHeaderByNumber retrieves a block header from the database by number, // caching it (associated with its hash) if found. func (bc *BlockChain) GetHeaderByNumber(number uint64) *types.Header { diff --git a/core/headerchain.go b/core/headerchain.go index 0e5215293d..9f82b367fa 100644 --- a/core/headerchain.go +++ b/core/headerchain.go @@ -370,10 +370,15 @@ func (hc *HeaderChain) HasHeader(hash common.Hash, number uint64) bool { return ok } +// GetBlockHashByNumber retrieves the block hash from the database by number. +func (hc *HeaderChain) GetBlockHashByNumber(number uint64) common.Hash { + return GetCanonicalHash(hc.chainDb, number) +} + // GetHeaderByNumber retrieves a block header from the database by number, // caching it (associated with its hash) if found. func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header { - hash := GetCanonicalHash(hc.chainDb, number) + hash := hc.GetBlockHashByNumber(number) if hash == (common.Hash{}) { return nil } diff --git a/eth/api_backend.go b/eth/api_backend.go index 91f392f94f..b918be35a0 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -81,19 +81,19 @@ func (b *EthApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil } -func (b *EthApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (b *EthApiBackend) StateByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, error) { // Pending state is only known by the miner if blockNr == rpc.PendingBlockNumber { - block, state := b.eth.miner.Pending() - return state, block.Header(), nil + return b.eth.TxPool().State().StateDB, nil } + // Otherwise resolve the block number and return its state - header, err := b.HeaderByNumber(ctx, blockNr) - if header == nil || err != nil { - return nil, nil, err + if blockNr == rpc.LatestBlockNumber { + return b.eth.BlockChain().State() } - stateDb, err := b.eth.BlockChain().StateAt(header.Root) - return stateDb, header, err + + blockHash := b.eth.BlockChain().GetBlockHashByNumber(uint64(blockNr)) + return b.eth.BlockChain().StateAt(blockHash) } func (b *EthApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) { diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 55bd5aa1ba..a0d310ffd6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -463,7 +463,7 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int { // given block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta // block numbers are also allowed. func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*big.Int, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, err := s.b.StateByNumber(ctx, blockNr) if state == nil || err != nil { return nil, err } @@ -550,7 +550,7 @@ func (s *PublicBlockChainAPI) GetUncleCountByBlockHash(ctx context.Context, bloc // GetCode returns the code stored at the given address in the state for the given block number. func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, err := s.b.StateByNumber(ctx, blockNr) if state == nil || err != nil { return nil, err } @@ -562,7 +562,7 @@ func (s *PublicBlockChainAPI) GetCode(ctx context.Context, address common.Addres // block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block // numbers are also allowed. func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.Address, key string, blockNr rpc.BlockNumber) (hexutil.Bytes, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, err := s.b.StateByNumber(ctx, blockNr) if state == nil || err != nil { return nil, err } @@ -583,10 +583,15 @@ type CallArgs struct { func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config) ([]byte, uint64, bool, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) - state, header, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, err := s.b.StateByNumber(ctx, blockNr) if state == nil || err != nil { return nil, 0, false, err } + header, err := s.b.HeaderByNumber(ctx, blockNr) + if header == nil || err != nil { + return nil, 0, false, err + } + // Set sender address or use a default if none specified addr := args.From if addr == (common.Address{}) { @@ -963,7 +968,7 @@ func (s *PublicTransactionPoolAPI) GetRawTransactionByBlockHashAndIndex(ctx cont // GetTransactionCount returns the number of transactions the given address has sent for the given block number func (s *PublicTransactionPoolAPI) GetTransactionCount(ctx context.Context, address common.Address, blockNr rpc.BlockNumber) (*hexutil.Uint64, error) { - state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr) + state, err := s.b.StateByNumber(ctx, blockNr) if state == nil || err != nil { return nil, err } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index af95d7906f..acd4c10dfd 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -49,7 +49,7 @@ type Backend interface { SetHead(number uint64) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) - StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) + StateByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, error) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) GetReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) GetTd(blockHash common.Hash) *big.Int diff --git a/les/api_backend.go b/les/api_backend.go index 56f617a7db..4379760dc2 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -71,12 +71,12 @@ func (b *LesApiBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumb return b.GetBlock(ctx, header.Hash()) } -func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (b *LesApiBackend) StateByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, error) { header, err := b.HeaderByNumber(ctx, blockNr) if header == nil || err != nil { - return nil, nil, err + return nil, err } - return light.NewState(ctx, header, b.eth.odr), header, nil + return light.NewState(ctx, header, b.eth.odr), nil } func (b *LesApiBackend) GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error) {