Commit 0b2ead8f authored by Conner Fromknecht's avatar Conner Fromknecht Committed by Matthew Slipper

feat: stop publishing txs after receiving confirmation

This change adds an additional IsWaitingForConfirmation method to the
txmgr.SendState, which returns true if it is aware of at least one mined
tx. This allows the txmgr to skip publishing new txs while we are
waiting for additional confirmation on a mined tx, which in turn reduces
the number of useless API calls we make to the backend provider. As an
additional benefit, this also reduces the likelihood of a false positive
sample from ShouldAbortImmediately since it will stop processing errors
while we have a mined tx.
parent 1bdd8e63
...@@ -100,3 +100,12 @@ func (s *SendState) ShouldAbortImmediately() bool { ...@@ -100,3 +100,12 @@ func (s *SendState) ShouldAbortImmediately() bool {
// threshold. // threshold.
return s.nonceTooLowCount >= s.safeAbortNonceTooLowCount return s.nonceTooLowCount >= s.safeAbortNonceTooLowCount
} }
// IsWaitingForConfirmation returns true if we have at least one confirmation on
// one of our txs.
func (s *SendState) IsWaitingForConfirmation() bool {
s.mu.RLock()
defer s.mu.RUnlock()
return len(s.minedTxs) > 0
}
...@@ -31,6 +31,7 @@ func processNSendErrors(sendState *txmgr.SendState, err error, n int) { ...@@ -31,6 +31,7 @@ func processNSendErrors(sendState *txmgr.SendState, err error, n int) {
func TestSendStateNoAbortAfterInit(t *testing.T) { func TestSendStateNoAbortAfterInit(t *testing.T) {
sendState := newSendState() sendState := newSendState()
require.False(t, sendState.ShouldAbortImmediately()) require.False(t, sendState.ShouldAbortImmediately())
require.False(t, sendState.IsWaitingForConfirmation())
} }
// TestSendStateNoAbortAfterProcessNilError asserts that nil errors are not // TestSendStateNoAbortAfterProcessNilError asserts that nil errors are not
...@@ -135,3 +136,26 @@ func TestSendStateSafeAbortWhileCallingNotMinedOnUnminedTx(t *testing.T) { ...@@ -135,3 +136,26 @@ func TestSendStateSafeAbortWhileCallingNotMinedOnUnminedTx(t *testing.T) {
sendState.TxNotMined(testHash) sendState.TxNotMined(testHash)
require.True(t, sendState.ShouldAbortImmediately()) require.True(t, sendState.ShouldAbortImmediately())
} }
// TestSendStateIsWaitingForConfirmationAfterTxMined asserts that we are waiting
// for confirmation after a tx is mined.
func TestSendStateIsWaitingForConfirmationAfterTxMined(t *testing.T) {
sendState := newSendState()
testHash2 := common.HexToHash("0x02")
sendState.TxMined(testHash)
require.True(t, sendState.IsWaitingForConfirmation())
sendState.TxMined(testHash2)
require.True(t, sendState.IsWaitingForConfirmation())
}
// TestSendStateIsNotWaitingForConfirmationAfterTxUnmined asserts that we are
// not waiting for confirmation after a tx is mined then unmined.
func TestSendStateIsNotWaitingForConfirmationAfterTxUnmined(t *testing.T) {
sendState := newSendState()
sendState.TxMined(testHash)
sendState.TxNotMined(testHash)
require.False(t, sendState.IsWaitingForConfirmation())
}
...@@ -206,6 +206,14 @@ func (m *SimpleTxManager) Send( ...@@ -206,6 +206,14 @@ func (m *SimpleTxManager) Send(
// Whenever a resubmission timeout has elapsed, bump the gas // Whenever a resubmission timeout has elapsed, bump the gas
// price and publish a new transaction. // price and publish a new transaction.
case <-time.After(m.cfg.ResubmissionTimeout): case <-time.After(m.cfg.ResubmissionTimeout):
// Avoid republishing if we are waiting for confirmation on an
// existing tx. This is primarily an optimization to reduce the
// number of API calls we make, but also reduces the chances of
// getting a false postive reading for ShouldAbortImmediately.
if sendState.IsWaitingForConfirmation() {
continue
}
// Submit and wait for the bumped traction to confirm. // Submit and wait for the bumped traction to confirm.
wg.Add(1) wg.Add(1)
go sendTxAsync() go sendTxAsync()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment