From 37950cad345a594cea9e5e8d0cbe407b6757b79c Mon Sep 17 00:00:00 2001 From: Zsolt Felfoldi Date: Fri, 14 Jun 2024 02:45:24 +0200 Subject: [PATCH] ethclient/lightclient: pending transaction debug --- cmd/bltest/main.go | 14 ++++++++ ethclient/lightclient/lightclient.go | 12 +++++-- ethclient/lightclient/transactions.go | 46 ++++++++++++++++++++++++--- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/cmd/bltest/main.go b/cmd/bltest/main.go index 884a218d70..0b42dd2245 100644 --- a/cmd/bltest/main.go +++ b/cmd/bltest/main.go @@ -169,6 +169,20 @@ loop: } testState(common.Address{}) testState(common.HexToAddress("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")) // WETH contract + + if txs, err := client.RandomPendingTxs(ctx, 5); err == nil { + log.Info("Tracking random pending transactions", "count", len(txs)) + for _, tx := range txs { + client.TrackTransaction(tx) + } + } else { + log.Error("Tracking random pending transactions", "error", err) + } + if count, err := client.PendingTransactionCount(ctx); err == nil { + log.Info("PendingTransactionCount ", "count", count) + } else { + log.Error("PendingTransactionCount ", "error", err) + } case <-ctx.Done(): break loop } diff --git a/ethclient/lightclient/lightclient.go b/ethclient/lightclient/lightclient.go index 1eb45d50b3..1261e97f89 100644 --- a/ethclient/lightclient/lightclient.go +++ b/ethclient/lightclient/lightclient.go @@ -313,7 +313,7 @@ func (c *Client) PendingNonceAt(ctx context.Context, account common.Address) (ui if len(pendingTxs) == 0 { return headNonce, nil } - return pendingTxs[len(pendingTxs)-1].Nonce(), nil + return pendingTxs[len(pendingTxs)-1].Nonce() + 1, nil } func (c *Client) PendingTransactionCount(ctx context.Context) (uint, error) { @@ -325,8 +325,16 @@ func (c *Client) PendingTransactionCount(ctx context.Context) (uint, error) { countCh := make(chan uint, len(allSenders)) errCh := make(chan error, len(allSenders)) for _, sender := range allSenders { + sender := sender go func() { - _, pendingTxs, err := c.nonceAndPendingTxs(ctx, head, sender) + nonce, pendingTxs, err := c.nonceAndPendingTxs(ctx, head, sender) + if len(pendingTxs) > 0 { + txNonces := make([]uint64, len(pendingTxs)) + for i, tx := range pendingTxs { + txNonces[i] = tx.Nonce() + } + log.Info("Pending transactions", "sender", sender, "head nonce", nonce, "tx nonces", txNonces) + } errCh <- err countCh <- uint(len(pendingTxs)) }() diff --git a/ethclient/lightclient/transactions.go b/ethclient/lightclient/transactions.go index b73e7c3d45..ceb22ea2cb 100644 --- a/ethclient/lightclient/transactions.go +++ b/ethclient/lightclient/transactions.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "math/big" + "math/rand" "sort" "sync" @@ -359,10 +360,6 @@ func (c *Client) cacheBlockTxPositions(block *types.Block) { // sendTransaction sends a transaction to the RPC server and adds it to the set of // tracked transactions. func (c *Client) sendTransaction(ctx context.Context, tx *types.Transaction) error { - sender, err := types.Sender(c.signer, tx) - if err != nil { - return nil - } data, err := tx.MarshalBinary() if err != nil { return err @@ -370,6 +367,14 @@ func (c *Client) sendTransaction(ctx context.Context, tx *types.Transaction) err if err := c.client.CallContext(ctx, nil, "eth_sendRawTransaction", hexutil.Encode(data)); err != nil { return err } + return c.TrackTransaction(tx) +} + +func (c *Client) TrackTransaction(tx *types.Transaction) error { + sender, err := types.Sender(c.signer, tx) + if err != nil { + return err + } c.trackedTxLock.Lock() c.markTxAsSeen(sender, tx) c.trackedTxLock.Unlock() @@ -400,10 +405,11 @@ func (c *Client) nonceAndPendingTxs(ctx context.Context, head *btypes.ExecutionH resultCh := make(chan pendingResult, len(senderTxs)) var reqCount int for txHash, trackedTx := range senderTxs { - if trackedTx.nonce <= proof.Nonce { + if trackedTx.nonce < proof.Nonce { continue } reqCount++ + txHash := txHash go func() { tx, isPending, err := c.getUncachedTxByHash(ctx, txHash, head.BlockNumber()) if err == nil && isPending { @@ -480,3 +486,33 @@ func (c *Client) markTxAsSeen(sender common.Address, tx *types.Transaction) { } senderTxs[tx.Hash()] = trackedTx{nonce: tx.Nonce(), lastSeen: c.headCounter} } + +func (c *Client) RandomPendingTxs(ctx context.Context, count int) (types.Transactions, error) { + var txc hexutil.Uint + err := c.client.CallContext(ctx, &txc, "eth_getBlockTransactionCountByNumber", "pending") + if err != nil { + return nil, err + } + txCount := int(txc) + if txCount == 0 { + return nil, errors.New("no pending transactions") + } + txs := make(types.Transactions, count) + for i := range txs { + var json *rpcTransaction + index := rand.Intn(txCount) + err := c.client.CallContext(ctx, &json, "eth_getTransactionByBlockNumberAndIndex", "pending", hexutil.Uint64(index)) + if err != nil { + return nil, err + } else if json == nil { + return nil, ethereum.NotFound + } else if _, r, _ := json.tx.RawSignatureValues(); r == nil { + return nil, errors.New("server returned transaction without signature") + } + if json.From != nil && json.BlockHash != nil { + setSenderFromServer(json.tx, *json.From, *json.BlockHash) + } + txs[i] = json.tx + } + return txs, nil +}