mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
ethclient/lightclient: use requestMap for tx/receipt requests
This commit is contained in:
parent
2d485d5972
commit
02b67cd9e7
1 changed files with 39 additions and 20 deletions
|
|
@ -40,15 +40,22 @@ const maxTxAge = 300 // sent transactions are typically remembered for an hour a
|
||||||
type txAndReceiptsFields struct {
|
type txAndReceiptsFields struct {
|
||||||
signer types.Signer
|
signer types.Signer
|
||||||
|
|
||||||
receiptsCache *lru.Cache[common.Hash, types.Receipts]
|
blockReceiptsCache *lru.Cache[common.Hash, types.Receipts]
|
||||||
receiptsRequests *requestMap[common.Hash, types.Receipts]
|
blockReceiptsRequests *requestMap[common.Hash, types.Receipts]
|
||||||
txPosCache *lru.Cache[common.Hash, txInBlock]
|
txPosCache *lru.Cache[common.Hash, txInBlock]
|
||||||
|
txByHashRequests *requestMap[common.Hash, txResult]
|
||||||
|
receiptByHashRequests *requestMap[common.Hash, *types.Receipt]
|
||||||
|
|
||||||
sentTxLock sync.Mutex
|
sentTxLock sync.Mutex
|
||||||
sentTxs map[common.Address]senderTxs
|
sentTxs map[common.Address]senderTxs
|
||||||
headCounter, lastHeadNumber uint64
|
headCounter, lastHeadNumber uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type txResult struct {
|
||||||
|
tx *types.Transaction
|
||||||
|
isPending bool
|
||||||
|
}
|
||||||
|
|
||||||
type txInBlock struct {
|
type txInBlock struct {
|
||||||
blockNumber uint64
|
blockNumber uint64
|
||||||
blockHash common.Hash // only considered valid if the block is canonical
|
blockHash common.Hash // only considered valid if the block is canonical
|
||||||
|
|
@ -63,15 +70,19 @@ type sentTx struct {
|
||||||
type senderTxs map[common.Hash]sentTx
|
type senderTxs map[common.Hash]sentTx
|
||||||
|
|
||||||
func (c *Client) initTxAndReceipts() {
|
func (c *Client) initTxAndReceipts() {
|
||||||
c.receiptsCache = lru.NewCache[common.Hash, types.Receipts](10)
|
c.blockReceiptsCache = lru.NewCache[common.Hash, types.Receipts](10)
|
||||||
c.txPosCache = lru.NewCache[common.Hash, txInBlock](10000)
|
c.txPosCache = lru.NewCache[common.Hash, txInBlock](10000)
|
||||||
c.sentTxs = make(map[common.Address]senderTxs)
|
c.sentTxs = make(map[common.Address]senderTxs)
|
||||||
c.signer = types.LatestSigner(c.elConfig)
|
c.signer = types.LatestSigner(c.elConfig)
|
||||||
c.receiptsRequests = newRequestMap[common.Hash, types.Receipts](c.requestBlockReceipts)
|
c.blockReceiptsRequests = newRequestMap[common.Hash, types.Receipts](c.requestBlockReceipts)
|
||||||
|
c.txByHashRequests = newRequestMap[common.Hash, txResult](c.requestTxByHash)
|
||||||
|
c.receiptByHashRequests = newRequestMap[common.Hash, *types.Receipt](c.requestReceiptByTxHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) closeTxAndReceipts() {
|
func (c *Client) closeTxAndReceipts() {
|
||||||
c.receiptsRequests.close()
|
c.blockReceiptsRequests.close()
|
||||||
|
c.txByHashRequests.close()
|
||||||
|
c.receiptByHashRequests.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getTxByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) {
|
func (c *Client) getTxByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, isPending bool, err error) {
|
||||||
|
|
@ -94,9 +105,15 @@ func (c *Client) getTxByHash(ctx context.Context, txHash common.Hash) (tx *types
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getUncachedTxByHash(ctx context.Context, txHash common.Hash, headBlockNumber uint64) (tx *types.Transaction, isPending bool, err error) {
|
func (c *Client) getUncachedTxByHash(ctx context.Context, txHash common.Hash, headBlockNumber uint64) (tx *types.Transaction, isPending bool, err error) {
|
||||||
tx, isPending, err = c.requestTxByHash(ctx, txHash)
|
req := c.txByHashRequests.request(txHash)
|
||||||
|
var txResult txResult
|
||||||
|
txResult, err = req.getResult(ctx)
|
||||||
|
req.release()
|
||||||
|
tx, isPending = txResult.tx, txResult.isPending
|
||||||
if err == nil && !isPending {
|
if err == nil && !isPending {
|
||||||
receipt, err := c.requestReceiptByTxHash(ctx, txHash)
|
req := c.receiptByHashRequests.request(txHash)
|
||||||
|
receipt, err := req.getResult(ctx)
|
||||||
|
req.release()
|
||||||
if err == ethereum.NotFound {
|
if err == ethereum.NotFound {
|
||||||
return tx, false, nil
|
return tx, false, nil
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +131,7 @@ func (c *Client) getUncachedTxByHash(ctx context.Context, txHash common.Hash, he
|
||||||
func (c *Client) getReceiptByTxHash(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
|
func (c *Client) getReceiptByTxHash(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
|
||||||
if pos, ok := c.txPosCache.Get(txHash); ok {
|
if pos, ok := c.txPosCache.Get(txHash); ok {
|
||||||
if hash, ok := c.getCachedHash(pos.blockNumber); ok && hash == pos.blockHash {
|
if hash, ok := c.getCachedHash(pos.blockNumber); ok && hash == pos.blockHash {
|
||||||
if receipts, ok := c.receiptsCache.Get(pos.blockHash); ok {
|
if receipts, ok := c.blockReceiptsCache.Get(pos.blockHash); ok {
|
||||||
if pos.index >= uint(len(receipts)) {
|
if pos.index >= uint(len(receipts)) {
|
||||||
return nil, errors.New("transaction index out of range")
|
return nil, errors.New("transaction index out of range")
|
||||||
}
|
}
|
||||||
|
|
@ -122,7 +139,9 @@ func (c *Client) getReceiptByTxHash(ctx context.Context, txHash common.Hash) (*t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
receipt, err := c.requestReceiptByTxHash(ctx, txHash)
|
req := c.receiptByHashRequests.request(txHash)
|
||||||
|
receipt, err := req.getResult(ctx)
|
||||||
|
req.release()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -171,10 +190,10 @@ func (c *Client) getReceiptByTxHash(ctx context.Context, txHash common.Hash) (*t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getBlockReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) {
|
func (c *Client) getBlockReceipts(ctx context.Context, blockHash common.Hash) (types.Receipts, error) {
|
||||||
if receipts, ok := c.receiptsCache.Get(blockHash); ok {
|
if receipts, ok := c.blockReceiptsCache.Get(blockHash); ok {
|
||||||
return receipts, nil
|
return receipts, nil
|
||||||
}
|
}
|
||||||
request := c.receiptsRequests.request(blockHash)
|
request := c.blockReceiptsRequests.request(blockHash)
|
||||||
block, err := c.getBlock(ctx, blockHash)
|
block, err := c.getBlock(ctx, blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -184,7 +203,7 @@ func (c *Client) getBlockReceipts(ctx context.Context, blockHash common.Hash) (t
|
||||||
receipts, err = c.validateBlockReceipts(block, receipts)
|
receipts, err = c.validateBlockReceipts(block, receipts)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
c.receiptsCache.Add(blockHash, receipts)
|
c.blockReceiptsCache.Add(blockHash, receipts)
|
||||||
}
|
}
|
||||||
request.release()
|
request.release()
|
||||||
return receipts, err
|
return receipts, err
|
||||||
|
|
@ -237,22 +256,22 @@ func (c *Client) validateBlockReceipts(block *types.Block, receipts types.Receip
|
||||||
return newReceipts, nil
|
return newReceipts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) requestTxByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) {
|
func (c *Client) requestTxByHash(ctx context.Context, hash common.Hash) (txResult, error) {
|
||||||
var json *rpcTransaction
|
var json *rpcTransaction
|
||||||
err = c.client.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
|
err := c.client.CallContext(ctx, &json, "eth_getTransactionByHash", hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return txResult{}, err
|
||||||
} else if json == nil {
|
} else if json == nil {
|
||||||
return nil, false, ethereum.NotFound
|
return txResult{}, ethereum.NotFound
|
||||||
} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
|
} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
|
||||||
return nil, false, errors.New("server returned transaction without signature")
|
return txResult{}, errors.New("server returned transaction without signature")
|
||||||
} else if json.tx.Hash() != hash {
|
} else if json.tx.Hash() != hash {
|
||||||
return nil, false, errors.New("invalid transaction hash")
|
return txResult{}, errors.New("invalid transaction hash")
|
||||||
}
|
}
|
||||||
if json.From != nil && json.BlockHash != nil {
|
if json.From != nil && json.BlockHash != nil {
|
||||||
setSenderFromServer(json.tx, *json.From, *json.BlockHash)
|
setSenderFromServer(json.tx, *json.From, *json.BlockHash)
|
||||||
}
|
}
|
||||||
return json.tx, json.BlockNumber == nil, nil
|
return txResult{tx: json.tx, isPending: json.BlockNumber == nil}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) requestReceiptByTxHash(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
|
func (c *Client) requestReceiptByTxHash(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue