mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-02-26 07:37:20 +00:00
ethclient: fix retrieval of pending block (#31504)
Since the block hash is not returned for pending blocks, ethclient cannot unmarshal into RPC block. This makes hash optional on rpc block and compute the hash locally for pending blocks to correctly key the tx sender cache.
a82303f4e3/internal/ethapi/api.go (L500-L504)
---------
Co-authored-by: lightclient <lightclient@protonmail.com>
This commit is contained in:
parent
701df4baad
commit
af9673b143
2 changed files with 37 additions and 6 deletions
|
|
@ -131,7 +131,7 @@ func (ec *Client) BlockReceipts(ctx context.Context, blockNrOrHash rpc.BlockNumb
|
|||
}
|
||||
|
||||
type rpcBlock struct {
|
||||
Hash common.Hash `json:"hash"`
|
||||
Hash *common.Hash `json:"hash"`
|
||||
Transactions []rpcTransaction `json:"transactions"`
|
||||
UncleHashes []common.Hash `json:"uncles"`
|
||||
Withdrawals []*types.Withdrawal `json:"withdrawals,omitempty"`
|
||||
|
|
@ -158,6 +158,12 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
|
|||
if err := json.Unmarshal(raw, &body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Pending blocks don't return a block hash, compute it for sender caching.
|
||||
if body.Hash == nil {
|
||||
tmp := head.Hash()
|
||||
body.Hash = &tmp
|
||||
}
|
||||
|
||||
// Quick-verify transaction and uncle lists. This mostly helps with debugging the server.
|
||||
if head.UncleHash == types.EmptyUncleHash && len(body.UncleHashes) > 0 {
|
||||
return nil, errors.New("server returned non-empty uncle list but block header indicates no uncles")
|
||||
|
|
@ -199,7 +205,7 @@ func (ec *Client) getBlock(ctx context.Context, method string, args ...interface
|
|||
txs := make([]*types.Transaction, len(body.Transactions))
|
||||
for i, tx := range body.Transactions {
|
||||
if tx.From != nil {
|
||||
setSenderFromServer(tx.tx, *tx.From, body.Hash)
|
||||
setSenderFromServer(tx.tx, *tx.From, *body.Hash)
|
||||
}
|
||||
txs[i] = tx.tx
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,6 +307,12 @@ func testTransactionInBlock(t *testing.T, client *rpc.Client) {
|
|||
if tx.Hash() != testTx2.Hash() {
|
||||
t.Fatalf("unexpected transaction: %v", tx)
|
||||
}
|
||||
|
||||
// Test pending block
|
||||
_, err = ec.BlockByNumber(context.Background(), big.NewInt(int64(rpc.PendingBlockNumber)))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func testChainID(t *testing.T, client *rpc.Client) {
|
||||
|
|
@ -619,6 +625,21 @@ func testAtFunctions(t *testing.T, client *rpc.Client) {
|
|||
if gas != 21000 {
|
||||
t.Fatalf("unexpected gas limit: %v", gas)
|
||||
}
|
||||
|
||||
// Verify that sender address of pending transaction is saved in cache.
|
||||
pendingBlock, err := ec.BlockByNumber(context.Background(), big.NewInt(int64(rpc.PendingBlockNumber)))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
// No additional RPC should be required, ensure the server is not asked by
|
||||
// canceling the context.
|
||||
sender, err := ec.TransactionSender(newCanceledContext(), pendingBlock.Transactions()[0], pendingBlock.Hash(), 0)
|
||||
if err != nil {
|
||||
t.Fatal("unable to recover sender:", err)
|
||||
}
|
||||
if sender != testAddr {
|
||||
t.Fatal("wrong sender:", sender)
|
||||
}
|
||||
}
|
||||
|
||||
func testTransactionSender(t *testing.T, client *rpc.Client) {
|
||||
|
|
@ -640,10 +661,7 @@ func testTransactionSender(t *testing.T, client *rpc.Client) {
|
|||
|
||||
// The sender address is cached in tx1, so no additional RPC should be required in
|
||||
// TransactionSender. Ensure the server is not asked by canceling the context here.
|
||||
canceledCtx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
<-canceledCtx.Done() // Ensure the close of the Done channel
|
||||
sender1, err := ec.TransactionSender(canceledCtx, tx1, block2.Hash(), 0)
|
||||
sender1, err := ec.TransactionSender(newCanceledContext(), tx1, block2.Hash(), 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -662,6 +680,13 @@ func testTransactionSender(t *testing.T, client *rpc.Client) {
|
|||
}
|
||||
}
|
||||
|
||||
func newCanceledContext() context.Context {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
<-ctx.Done() // Ensure the close of the Done channel
|
||||
return ctx
|
||||
}
|
||||
|
||||
func sendTransaction(ec *ethclient.Client) error {
|
||||
chainID, err := ec.ChainID(context.Background())
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in a new issue