4

If I have a very busy account, let's say I'm an exchange and use a relay account or something / a hot wallet maybe to process withdrawels, which processes and creates millions of transactions, will there be an issue with a steadily increasing transaction nonce?

Is there any technical upper limit for transaction nonces, e.g., in the underlying data types used?

4

From github - Go Ethereum - core/types/transaction.go, lines 46-54:

type txdata struct {
    AccountNonce    uint64
    Price, GasLimit *big.Int
    Recipient       *common.Address `rlp:"nil"` // nil means contract creation
    Amount          *big.Int
    Payload         []byte
    V               byte     // signature
    R, S            *big.Int // signature
}

AccountNonce is a 64 bit unsigned integer, with a range from 0 to 2^64-1 (which is 18,446,744,073,709,551,616 from Unsigned and Signed Integers ).

From a perusal of the Go Ethereum source code, there does not seem to be any other restrictions placed on the range of the nonce.

So, you can safely create millions (x millions x millions) of transactions from the same account.


And if you are interested, here is the output for my checks of the comparison operators on the nonce variable.

user@Kumquat:~/EthereumSource/go-ethereum$ find . -type f -exec grep -H Nonce {} \; | grep "<"
./core/chain_pow.go:func verifyNoncesFromHeaders(checker pow.PoW, headers []*types.Header) (chan<- struct{}, <-chan nonceCheckResult) {
./core/chain_pow.go:func verifyNoncesFromBlocks(checker pow.PoW, blocks []*types.Block) (chan<- struct{}, <-chan nonceCheckResult) {
./core/chain_pow.go:func verifyNonces(checker pow.PoW, items []pow.Block) (chan<- struct{}, <-chan nonceCheckResult) {
./core/types/transaction_test.go:               t.Errorf("invalid nonce ordering: tx #%d (A=%x N=%v) < tx #%d (A=%x N=%v)", i, fromi[:4], txi.Nonce(), i+j, fromj[:4], txj.Nonce())
./core/types/transaction.go:func (s TxByNonce) Less(i, j int) bool { return s[i].data.AccountNonce < s[j].data.AccountNonce }
./core/tx_pool.go:          if pool.pendingState.GetNonce(addr) <= tx.Nonce() {
./core/tx_pool.go:          if tx.Nonce() < trueNonce || balance.Cmp(tx.Cost()) < 0 {
./core/tx_pool.go:      if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 {
./core/tx_pool.go:              if prev, ok := gaps[sender]; !ok || tx.Nonce() < prev {
./core/tx_pool.go:func (q txQueue) Less(i, j int) bool { return q[i].Nonce() < q[j].Nonce() }
user@Kumquat:~/EthereumSource/go-ethereum$ find . -type f -exec grep -H Nonce {} \; | grep ">"
./core/types/transaction_test.go:           if fromi == fromj && txi.Nonce() > txj.Nonce() {
./core/types/transaction.go:        if accTxs, ok := byNonce[acc]; ok && len(accTxs) > 0 {
./core/tx_pool.go:  if currentState.GetNonce(from) > tx.Nonce() {
./core/tx_pool.go:          if entry.Nonce() > guessedNonce {
./core/tx_pool.go:      if past := state.GetNonce(sender) > tx.Nonce(); past || balance.Cmp(tx.Cost()) < 0 {
./core/tx_pool.go:          if gap, ok := gaps[sender]; ok && tx.Nonce() >= gap {

There does not seem to be any checks for an upper limit to the nonce.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.