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

Lock when auto-filling transaction nonce #14483

Merged
merged 2 commits into from
May 19, 2017
Merged
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
23 changes: 23 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"fmt"
"math/big"
"strings"
"sync"
"time"

"github.com/ethereum/go-ethereum/accounts"
Expand Down Expand Up @@ -890,6 +891,12 @@ type PublicTransactionPoolAPI struct {
b Backend
}

// nonceMutex is a global mutex for locking the nonce while a transaction
// is being submitted. This should be used when a nonce has not been provided by the user,
// and we get a nonce from the pools. The mutex prevents the (an identical nonce) from being
// read again during the time that the first transaction is being signed.
var nonceMutex sync.RWMutex

// NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
func NewPublicTransactionPoolAPI(b Backend) *PublicTransactionPoolAPI {
return &PublicTransactionPoolAPI{b}
Expand Down Expand Up @@ -1170,6 +1177,14 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c
// SendTransaction creates a transaction for the given argument, sign it and submit it to the
// transaction pool.
func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) {

if args.Nonce == nil {
// We'll need to set nonce from pool, and thus we need to lock here
nonceMutex.Lock()
defer nonceMutex.Unlock()

}

// Set some sanity defaults and terminate on failure
if err := args.setDefaults(ctx, s.b); err != nil {
return common.Hash{}, err
Expand Down Expand Up @@ -1257,6 +1272,14 @@ type SignTransactionResult struct {
// The node needs to have the private key of the account corresponding with
// the given from address and it needs to be unlocked.
func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) {

if args.Nonce == nil {
// We'll need to set nonce from pool, and thus we need to lock here
nonceMutex.Lock()
defer nonceMutex.Unlock()

}

if err := args.setDefaults(ctx, s.b); err != nil {
return nil, err
}
Expand Down