Skip to content

Commit

Permalink
fix: Eliminate local transaction nonce cache. (#4839)
Browse files Browse the repository at this point in the history
  • Loading branch information
attila-lendvai authored Oct 8, 2024
1 parent a8066a2 commit e4e4520
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 92 deletions.
39 changes: 16 additions & 23 deletions pkg/transaction/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,6 @@ func (t *transactionService) Send(ctx context.Context, request *TxRequest, boost
return common.Hash{}, err
}

err = t.putNonce(nonce + 1)
if err != nil {
return common.Hash{}, err
}

txHash = signedTx.Hash()

err = t.store.Put(storedTransactionKey(txHash), StoredTransaction{
Expand Down Expand Up @@ -353,10 +348,6 @@ func (t *transactionService) suggestedFeeAndTip(ctx context.Context, gasPrice *b

}

func (t *transactionService) nonceKey() string {
return fmt.Sprintf("%s%x", noncePrefix, t.sender)
}

func storedTransactionKey(txHash common.Hash) string {
return fmt.Sprintf("%s%x", storedTransactionPrefix, txHash)
}
Expand All @@ -371,26 +362,28 @@ func (t *transactionService) nextNonce(ctx context.Context) (uint64, error) {
return 0, err
}

var nonce uint64
err = t.store.Get(t.nonceKey(), &nonce)
pendingTxs, err := t.PendingTransactions()
if err != nil {
// If no nonce was found locally used whatever we get from the backend.
if errors.Is(err, storage.ErrNotFound) {
return onchainNonce, nil
}
return 0, err
}

// If the nonce onchain is larger than what we have there were external
// transactions and we need to update our nonce.
if onchainNonce > nonce {
return onchainNonce, nil
pendingTxs = t.filterPendingTransactions(t.ctx, pendingTxs)

// PendingNonceAt returns the nonce we should use, but we will
// compare this to our pending tx list, therefore the -1.
var maxNonce uint64 = onchainNonce - 1
for _, txHash := range pendingTxs {
trx, _, err := t.backend.TransactionByHash(ctx, txHash)

if err != nil {
t.logger.Error(err, "pending transaction not found", "tx", txHash)
return 0, err
}

maxNonce = max(maxNonce, trx.Nonce())
}
return nonce, nil
}

func (t *transactionService) putNonce(nonce uint64) error {
return t.store.Put(t.nonceKey(), nonce)
return maxNonce + 1, nil
}

// WaitForReceipt waits until either the transaction with the given hash has
Expand Down
69 changes: 0 additions & 69 deletions pkg/transaction/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ import (
"github.com/ethersphere/bee/v2/pkg/util/testutil"
)

func nonceKey(sender common.Address) string {
return fmt.Sprintf("transaction_nonce_%x", sender)
}

func signerMockForTransaction(t *testing.T, signedTx *types.Transaction, sender common.Address, signerChainID *big.Int) crypto.Signer {
t.Helper()
return signermock.New(
Expand Down Expand Up @@ -66,10 +62,6 @@ func signerMockForTransaction(t *testing.T, signedTx *types.Transaction, sender
t.Fatalf("signing transaction with wrong gasprice. wanted %d, got %d", signedTx.GasPrice(), transaction.GasPrice())
}

if transaction.Nonce() != signedTx.Nonce() {
t.Fatalf("signing transaction with wrong nonce. wanted %d, got %d", signedTx.Nonce(), transaction.Nonce())
}

return signedTx, nil
}),
signermock.WithEthereumAddressFunc(func() (common.Address, error) {
Expand Down Expand Up @@ -112,10 +104,6 @@ func TestTransactionSend(t *testing.T) {
Value: value,
}
store := storemock.NewStateStore()
err := store.Put(nonceKey(sender), nonce)
if err != nil {
t.Fatal(err)
}

transactionService, err := transaction.NewService(logger, sender,
backendmock.New(
Expand Down Expand Up @@ -167,15 +155,6 @@ func TestTransactionSend(t *testing.T) {
t.Fatal("returning wrong transaction hash")
}

var storedNonce uint64
err = store.Get(nonceKey(sender), &storedNonce)
if err != nil {
t.Fatal(err)
}
if storedNonce != nonce+1 {
t.Fatalf("nonce not stored correctly: want %d, got %d", nonce+1, storedNonce)
}

storedTransaction, err := transactionService.StoredTransaction(txHash)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -238,10 +217,6 @@ func TestTransactionSend(t *testing.T) {
MinEstimatedGasLimit: estimatedGasLimit,
}
store := storemock.NewStateStore()
err := store.Put(nonceKey(sender), nonce)
if err != nil {
t.Fatal(err)
}

transactionService, err := transaction.NewService(logger, sender,
backendmock.New(
Expand Down Expand Up @@ -287,15 +262,6 @@ func TestTransactionSend(t *testing.T) {
t.Fatal("returning wrong transaction hash")
}

var storedNonce uint64
err = store.Get(nonceKey(sender), &storedNonce)
if err != nil {
t.Fatal(err)
}
if storedNonce != nonce+1 {
t.Fatalf("nonce not stored correctly: want %d, got %d", nonce+1, storedNonce)
}

storedTransaction, err := transactionService.StoredTransaction(txHash)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -363,10 +329,6 @@ func TestTransactionSend(t *testing.T) {
Value: value,
}
store := storemock.NewStateStore()
err := store.Put(nonceKey(sender), nonce)
if err != nil {
t.Fatal(err)
}

transactionService, err := transaction.NewService(logger, sender,
backendmock.New(
Expand Down Expand Up @@ -418,15 +380,6 @@ func TestTransactionSend(t *testing.T) {
t.Fatal("returning wrong transaction hash")
}

var storedNonce uint64
err = store.Get(nonceKey(sender), &storedNonce)
if err != nil {
t.Fatal(err)
}
if storedNonce != nonce+1 {
t.Fatalf("nonce not stored correctly: want %d, got %d", nonce+1, storedNonce)
}

storedTransaction, err := transactionService.StoredTransaction(txHash)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -534,15 +487,6 @@ func TestTransactionSend(t *testing.T) {
if !bytes.Equal(txHash.Bytes(), signedTx.Hash().Bytes()) {
t.Fatal("returning wrong transaction hash")
}

var storedNonce uint64
err = store.Get(nonceKey(sender), &storedNonce)
if err != nil {
t.Fatal(err)
}
if storedNonce != nonce+1 {
t.Fatalf("did not store nonce correctly. wanted %d, got %d", nonce+1, storedNonce)
}
})

t.Run("send_skipped_nonce", func(t *testing.T) {
Expand All @@ -565,10 +509,6 @@ func TestTransactionSend(t *testing.T) {
Value: value,
}
store := storemock.NewStateStore()
err := store.Put(nonceKey(sender), nonce)
if err != nil {
t.Fatal(err)
}

transactionService, err := transaction.NewService(logger, sender,
backendmock.New(
Expand Down Expand Up @@ -614,15 +554,6 @@ func TestTransactionSend(t *testing.T) {
if !bytes.Equal(txHash.Bytes(), signedTx.Hash().Bytes()) {
t.Fatal("returning wrong transaction hash")
}

var storedNonce uint64
err = store.Get(nonceKey(sender), &storedNonce)
if err != nil {
t.Fatal(err)
}
if storedNonce != nextNonce+1 {
t.Fatalf("did not store nonce correctly. wanted %d, got %d", nextNonce+1, storedNonce)
}
})
}

Expand Down

0 comments on commit e4e4520

Please sign in to comment.