[rpc] Fix cache lead to inconsistent result (#3733)

* Fix cache lead to inconsistent result

* update

* Add latest block real number to cache

* Fix cache
pull/3739/head
MathxH Chen 4 years ago committed by GitHub
parent 73ab26cf4e
commit c005b3b002
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 35
      rpc/blockchain.go

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"math/big"
"strconv"
"time"
"github.com/ethereum/go-ethereum/common"
@ -160,16 +161,6 @@ func (s *PublicBlockchainService) GetBlockByNumber(
ctx context.Context, blockNumber BlockNumber, opts interface{},
) (response StructuredResponse, err error) {
blockNum := blockNumber.EthBlockNumber()
if block, ok := s.blockCache.Get(uint64(blockNum)); ok {
return block.(StructuredResponse), nil
}
err = s.wait(ctx)
if err != nil {
return nil, err
}
// Process arguments based on version
var blockArgs *rpc_common.BlockArgs
blockArgs, ok := opts.(*rpc_common.BlockArgs)
@ -181,6 +172,19 @@ func (s *PublicBlockchainService) GetBlockByNumber(
}
blockArgs.InclTx = true
blockNum := blockNumber.EthBlockNumber()
if blockNum != rpc.LatestBlockNumber && blockNum != rpc.PendingBlockNumber {
cacheKey := combineCacheKey(uint64(blockNum), s.version, blockArgs)
if block, ok := s.blockCache.Get(cacheKey); ok {
return block.(StructuredResponse), nil
}
}
err = s.wait(ctx)
if err != nil {
return nil, err
}
// Some Ethereum tools (such as Truffle) rely on being able to query for future blocks without the chain returning errors.
// These tools implement retry mechanisms that will query & retry for a given block until it has been finalized.
// Throwing an error like "requested block number greater than current block number" breaks this retry functionality.
@ -227,7 +231,10 @@ func (s *PublicBlockchainService) GetBlockByNumber(
}
}
s.blockCache.Add(uint64(blockNum), response)
if blockNum != rpc.PendingBlockNumber {
cacheKey := combineCacheKey(blk.NumberU64(), s.version, blockArgs)
s.blockCache.Add(cacheKey, response)
}
return response, err
}
@ -812,3 +819,9 @@ func isBlockGreaterThanLatest(hmy *hmy.Harmony, blockNum rpc.BlockNumber) bool {
}
return uint64(blockNum) > hmy.CurrentBlock().NumberU64()
}
func combineCacheKey(number uint64, version Version, blockArgs *rpc_common.BlockArgs) string {
// no need format blockArgs.Signers[] as a part of cache key
// because it's not input from rpc caller, it's caculate with blockArgs.WithSigners
return strconv.FormatUint(number, 10) + strconv.FormatInt(int64(version), 10) + strconv.FormatBool(blockArgs.WithSigners) + strconv.FormatBool(blockArgs.InclTx) + strconv.FormatBool(blockArgs.FullTx) + strconv.FormatBool(blockArgs.InclStaking)
}

Loading…
Cancel
Save