Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
8dc16176
Unverified
Commit
8dc16176
authored
Sep 29, 2023
by
Michael de Hoog
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code review fixes
parent
753c36ca
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
43 additions
and
44 deletions
+43
-44
txmgr.go
op-service/txmgr/txmgr.go
+43
-44
No files found.
op-service/txmgr/txmgr.go
View file @
8dc16176
...
...
@@ -294,13 +294,22 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t
sendState
:=
NewSendState
(
m
.
cfg
.
SafeAbortNonceTooLowCount
,
m
.
cfg
.
TxNotInMempoolTimeout
)
receiptChan
:=
make
(
chan
*
types
.
Receipt
,
1
)
sendTx
:=
func
(
tx
*
types
.
Transaction
,
bumpFees
bool
)
*
types
.
Transaction
{
return
m
.
publishAndWaitForTx
(
ctx
,
tx
,
sendState
,
receiptChan
,
bumpFees
,
wg
.
Done
)
publishAndWait
:=
func
(
tx
*
types
.
Transaction
,
bumpFees
bool
)
*
types
.
Transaction
{
tx
,
published
:=
m
.
publishTx
(
ctx
,
tx
,
sendState
,
bumpFees
)
if
published
{
go
func
()
{
defer
wg
.
Done
()
m
.
waitForTx
(
ctx
,
tx
,
sendState
,
receiptChan
)
}()
}
else
{
wg
.
Done
()
}
return
tx
}
// Immediately publish a transaction before starting the resumbission loop
wg
.
Add
(
1
)
tx
=
sendTx
(
tx
,
false
)
tx
=
publishAndWait
(
tx
,
false
)
ticker
:=
time
.
NewTicker
(
m
.
cfg
.
ResubmissionTimeout
)
defer
ticker
.
Stop
()
...
...
@@ -318,7 +327,7 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t
return
nil
,
errors
.
New
(
"aborted transaction sending"
)
}
wg
.
Add
(
1
)
tx
=
sendTx
(
tx
,
true
)
tx
=
publishAndWait
(
tx
,
true
)
case
<-
ctx
.
Done
()
:
return
nil
,
ctx
.
Err
()
...
...
@@ -331,43 +340,35 @@ func (m *SimpleTxManager) sendTx(ctx context.Context, tx *types.Transaction) (*t
}
}
// publishAndWaitForTx publishes the transaction to the transaction pool and then waits for it with [waitMined].
// It should be called in a new go-routine. It will send the receipt to receiptChan in a non-blocking way if a receipt is found
// for the transaction.
func
(
m
*
SimpleTxManager
)
publishAndWaitForTx
(
ctx
context
.
Context
,
tx
*
types
.
Transaction
,
sendState
*
SendState
,
receiptChan
chan
*
types
.
Receipt
,
bumpFees
bool
,
done
func
())
*
types
.
Transaction
{
waiting
:=
false
defer
func
()
{
if
!
waiting
{
done
()
}
}()
// publishTx publishes the transaction to the transaction pool. If it receives any underpriced errors
// it will bump the fees and retry.
// Returns the latest fee bumped tx, and a boolean indicating whether the tx was sent or not
func
(
m
*
SimpleTxManager
)
publishTx
(
ctx
context
.
Context
,
tx
*
types
.
Transaction
,
sendState
*
SendState
,
bumpFeesImmediately
bool
)
(
*
types
.
Transaction
,
bool
)
{
updateLogFields
:=
func
(
tx
*
types
.
Transaction
)
log
.
Logger
{
return
m
.
l
.
New
(
"hash"
,
tx
.
Hash
(),
"nonce"
,
tx
.
Nonce
(),
"gasTipCap"
,
tx
.
GasTipCap
(),
"gasFeeCap"
,
tx
.
GasFeeCap
())
}
l
:=
updateLogFields
(
tx
)
l
.
Info
(
"Publishing transaction"
)
t
:=
time
.
Now
()
for
{
if
bumpFees
{
if
bumpFees
Immediately
{
newTx
,
err
:=
m
.
increaseGasPrice
(
ctx
,
tx
)
if
err
!=
nil
{
l
.
Error
(
"unable to increase gas"
,
"err"
,
err
)
m
.
metr
.
TxPublished
(
"bump_failed"
)
return
tx
return
tx
,
false
}
tx
=
newTx
sendState
.
bumpCount
++
l
=
updateLogFields
(
tx
)
}
bumpFees
=
true
// bump fees next loop
bumpFees
Immediately
=
true
// bump fees next loop
if
sendState
.
IsWaitingForConfirmation
()
{
// there is a chance the previous tx goes into "waiting for confirmation" state
// during the increaseGasPrice call; continue waiting rather than resubmit the tx
return
tx
return
tx
,
false
}
cCtx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
m
.
cfg
.
NetworkTimeout
)
...
...
@@ -376,7 +377,9 @@ func (m *SimpleTxManager) publishAndWaitForTx(ctx context.Context, tx *types.Tra
sendState
.
ProcessSendError
(
err
)
if
err
==
nil
{
break
m
.
metr
.
TxPublished
(
""
)
log
.
Info
(
"Transaction successfully published"
)
return
tx
,
true
}
switch
{
...
...
@@ -405,30 +408,26 @@ func (m *SimpleTxManager) publishAndWaitForTx(ctx context.Context, tx *types.Tra
}
// on non-underpriced error return immediately; will retry on next resubmission timeout
return
tx
return
tx
,
false
}
}
m
.
metr
.
TxPublished
(
""
)
log
.
Info
(
"Transaction successfully published"
)
waiting
=
true
go
func
()
{
defer
done
()
// Poll for the transaction to be ready & then send the result to receiptChan
receipt
,
err
:=
m
.
waitMined
(
ctx
,
tx
,
sendState
)
if
err
!=
nil
{
// this will happen if the tx was successfully replaced by a tx with bumped fees
log
.
Info
(
"Transaction receipt not found"
,
"err"
,
err
)
return
}
select
{
case
receiptChan
<-
receipt
:
m
.
metr
.
RecordTxConfirmationLatency
(
time
.
Since
(
t
)
.
Milliseconds
())
default
:
}
}()
return
tx
// waitForTx calls waitMined, and then sends the receipt to receiptChan in a non-blocking way if a receipt is found
// for the transaction. It should be called in a separate goroutine.
func
(
m
*
SimpleTxManager
)
waitForTx
(
ctx
context
.
Context
,
tx
*
types
.
Transaction
,
sendState
*
SendState
,
receiptChan
chan
*
types
.
Receipt
)
{
t
:=
time
.
Now
()
// Poll for the transaction to be ready & then send the result to receiptChan
receipt
,
err
:=
m
.
waitMined
(
ctx
,
tx
,
sendState
)
if
err
!=
nil
{
// this will happen if the tx was successfully replaced by a tx with bumped fees
log
.
Info
(
"Transaction receipt not found"
,
"err"
,
err
)
return
}
select
{
case
receiptChan
<-
receipt
:
m
.
metr
.
RecordTxConfirmationLatency
(
time
.
Since
(
t
)
.
Milliseconds
())
default
:
}
}
// waitMined waits for the transaction to be mined or for the context to be cancelled.
...
...
@@ -512,7 +511,7 @@ func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transa
}
bumpedTip
,
bumpedFee
:=
updateFees
(
tx
.
GasTipCap
(),
tx
.
GasFeeCap
(),
tip
,
basefee
,
m
.
l
)
// Make sure increase is at most
5x
the suggested values
// Make sure increase is at most
[FeeLimitMultiplier]
the suggested values
maxTip
:=
new
(
big
.
Int
)
.
Mul
(
tip
,
big
.
NewInt
(
int64
(
m
.
cfg
.
FeeLimitMultiplier
)))
if
bumpedTip
.
Cmp
(
maxTip
)
>
0
{
return
nil
,
fmt
.
Errorf
(
"bumped tip 0x%s is over %dx multiple of the suggested value"
,
bumpedTip
.
Text
(
16
),
m
.
cfg
.
FeeLimitMultiplier
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment