Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Eliminate local transaction nonce cache. #4839

Merged
merged 1 commit into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading