Skip to content

Commit

Permalink
Change key for chainID (smartcontractkit#533)
Browse files Browse the repository at this point in the history
  • Loading branch information
kalverra authored Feb 10, 2023
1 parent 57de50e commit d8ec2a7
Showing 1 changed file with 54 additions and 40 deletions.
94 changes: 54 additions & 40 deletions blockchain/nonce_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package blockchain

import (
"context"
"fmt"
"math/big"
"sync"

Expand All @@ -10,16 +11,21 @@ import (

// Used for when running tests on a live test network, so tests can share nonces and run in parallel on the same network
var (
globalNonceManager = make(map[*big.Int]*NonceSettings)
globalNonceManager = make(map[uint64]*NonceSettings)
globalNonceLock sync.Mutex
)

// useGlobalNonceManager for when running tests on a non-simulated network
func useGlobalNonceManager(chainId *big.Int) *NonceSettings {
if _, ok := globalNonceManager[chainId]; !ok {
globalNonceManager[chainId] = newNonceSettings()
go globalNonceManager[chainId].watchInstantTransactions()
globalNonceLock.Lock()
defer globalNonceLock.Unlock()
if _, ok := globalNonceManager[chainId.Uint64()]; !ok {
fmt.Printf("Using a new Global Nonce Manager for chain %d\n%v", chainId.Uint64(), globalNonceManager)
globalNonceManager[chainId.Uint64()] = newNonceSettings()
go globalNonceManager[chainId.Uint64()].watchInstantTransactions()
}
return globalNonceManager[chainId]

return globalNonceManager[chainId.Uint64()]
}

// convenience function
Expand Down Expand Up @@ -50,41 +56,6 @@ type NonceSettings struct {
sentChan chan string
}

// GetNonce keep tracking of nonces per address, add last nonce for addr if the map is empty
func (e *EthereumClient) GetNonce(ctx context.Context, addr common.Address) (uint64, error) {
e.NonceSettings.NonceMu.Lock()
defer e.NonceSettings.NonceMu.Unlock()
if _, ok := e.NonceSettings.Nonces[addr.Hex()]; !ok {
pendingNonce, err := e.Client.PendingNonceAt(ctx, addr)
if err != nil {
return 0, err
}
e.NonceSettings.Nonces[addr.Hex()] = pendingNonce

e.NonceSettings.instantNoncesMu.Lock()
e.NonceSettings.instantNonces[addr.Hex()] = pendingNonce
e.NonceSettings.instantNoncesMu.Unlock()

return pendingNonce, nil
}
e.NonceSettings.Nonces[addr.Hex()]++
return e.NonceSettings.Nonces[addr.Hex()], nil
}

// PeekPendingNonce returns the current pending nonce for the address. Does not change any nonce settings state
func (e *EthereumClient) PeekPendingNonce(addr common.Address) (uint64, error) {
e.NonceSettings.NonceMu.Lock()
defer e.NonceSettings.NonceMu.Unlock()
if _, ok := e.NonceSettings.Nonces[addr.Hex()]; !ok {
pendingNonce, err := e.Client.PendingNonceAt(context.Background(), addr)
if err != nil {
return 0, err
}
e.NonceSettings.Nonces[addr.Hex()] = pendingNonce
}
return e.NonceSettings.Nonces[addr.Hex()], nil
}

// watchInstantTransactions should only be called when minConfirmations for the chain is 0, generally an L2 chain.
// This helps meter out transactions to L2 chains, so that nonces only send in order. For most (if not all) L2 chains,
// the mempool is small or non-existent, meaning we can't send nonces out of order, otherwise the tx is instantly
Expand Down Expand Up @@ -135,6 +106,49 @@ func (ns *NonceSettings) sentInstantTransaction(fromAddr string) {
ns.sentChan <- fromAddr
}

// GetNonce keep tracking of nonces per address, add last nonce for addr if the map is empty
func (e *EthereumClient) GetNonce(ctx context.Context, addr common.Address) (uint64, error) {
e.NonceSettings.NonceMu.Lock()
defer e.NonceSettings.NonceMu.Unlock()

// See current state of the nonce manager, handy for debugging
// fmt.Println("-------Nonce Manager Current State-----------------")
// for address, nonce := range e.NonceSettings.Nonces {
// fmt.Printf("%s: %d\n", address, nonce)
// }
// fmt.Println("---------------------------------------------------")

if _, ok := e.NonceSettings.Nonces[addr.Hex()]; !ok {
pendingNonce, err := e.Client.PendingNonceAt(ctx, addr)
if err != nil {
return 0, err
}
e.NonceSettings.Nonces[addr.Hex()] = pendingNonce

e.NonceSettings.instantNoncesMu.Lock()
e.NonceSettings.instantNonces[addr.Hex()] = pendingNonce
e.NonceSettings.instantNoncesMu.Unlock()

return pendingNonce, nil
}
e.NonceSettings.Nonces[addr.Hex()]++
return e.NonceSettings.Nonces[addr.Hex()], nil
}

// PeekPendingNonce returns the current pending nonce for the address. Does not change any nonce settings state
func (e *EthereumClient) PeekPendingNonce(addr common.Address) (uint64, error) {
e.NonceSettings.NonceMu.Lock()
defer e.NonceSettings.NonceMu.Unlock()
if _, ok := e.NonceSettings.Nonces[addr.Hex()]; !ok {
pendingNonce, err := e.Client.PendingNonceAt(context.Background(), addr)
if err != nil {
return 0, err
}
e.NonceSettings.Nonces[addr.Hex()] = pendingNonce
}
return e.NonceSettings.Nonces[addr.Hex()], nil
}

type instantTxRegistration struct {
fromAddr string
nonce uint64
Expand Down

0 comments on commit d8ec2a7

Please sign in to comment.