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

feat: aggregator bump fee if transaction was not included #1286

Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
146 commits
Select commit Hold shift + click to select a range
ba9112a
Add first version of retry connection in Go
entropidelic Oct 16, 2024
42b4ed3
Add some docs
entropidelic Oct 16, 2024
896b98c
feat: basic aggregator bump modelling
MarcosNicolau Oct 17, 2024
dceaa0a
fix: gas limit for gas fee cap
MarcosNicolau Oct 17, 2024
61a64df
fix: gas limit calculation
MarcosNicolau Oct 18, 2024
6873cbe
fix: exiting tx receipt wait when context times out
MarcosNicolau Oct 18, 2024
b5bf04e
feat: retryWithData and without, generic pointer for return type, inf…
MarcosNicolau Oct 21, 2024
8bfd336
Add first version of retry connection in Go
entropidelic Oct 16, 2024
9cb6780
Add some docs
entropidelic Oct 16, 2024
2627659
feat: retryWithData and without, generic pointer for return type, inf…
MarcosNicolau Oct 21, 2024
90c4290
feat: SendAggregatedResponse with infinite retry
MarcosNicolau Oct 21, 2024
10597b0
feat: retry function with bumping fee
MarcosNicolau Oct 21, 2024
dbc7d60
docs: SendTransactionWithInfiniteRetryAndBumpingGasPrice
MarcosNicolau Oct 21, 2024
cc9b765
refactor: remove beforeTransaction
MarcosNicolau Oct 21, 2024
bf7dad5
fix: unrecoverable errs
MarcosNicolau Oct 21, 2024
72db766
feat: infinite retry for Retry without data
MarcosNicolau Oct 21, 2024
ecaf600
feat: infinite retry for Retry without data
MarcosNicolau Oct 21, 2024
4c2f00d
add retries to avs_subscriber
PatStiles Oct 22, 2024
9e53e56
add retries to avs_writer
PatStiles Oct 22, 2024
27c8cc6
add start to basic retry test in aggregator
PatStiles Oct 22, 2024
5fa0a28
add retries to aggregator
PatStiles Oct 22, 2024
2ec553b
add constants to connections
PatStiles Oct 22, 2024
34a80cc
Change subscriber function call
PatStiles Oct 22, 2024
99aa094
refactor: clearer math in bump calculation
MarcosNicolau Oct 22, 2024
b614916
refactor: retry remove i
MarcosNicolau Oct 22, 2024
527489b
refactor: remove SendTransactionWithInfiniteRetryAndBumpingGasPrice
MarcosNicolau Oct 22, 2024
5abc31e
refactor: gas price bump based on last bump
MarcosNicolau Oct 22, 2024
6f85dda
docs: SendAggregatedResponse and gas price calc
MarcosNicolau Oct 22, 2024
96f2ace
feat: metrics for bumped gas price
MarcosNicolau Oct 22, 2024
3469101
chore: grafana view for metrics
MarcosNicolau Oct 22, 2024
001eeab
add retryable functions to operator
PatStiles Oct 22, 2024
04375dd
refactor connection_test
PatStiles Oct 22, 2024
7d8660b
fix: gas price bump calculation
MarcosNicolau Oct 22, 2024
529fbe4
rm old waitForTransaction Function
PatStiles Oct 23, 2024
30a053d
feat: new gas price algorithm for respondtotask
MarcosNicolau Oct 23, 2024
071172b
Merge branch 'staging' into 311-aggregator-wait-for-receipt-for-1-min…
MarcosNicolau Oct 23, 2024
21b5e2a
chore: update metrics json
MarcosNicolau Oct 23, 2024
8e10a7e
chore: backoff dep
MarcosNicolau Oct 23, 2024
b1453b2
chore: show only aggregator in bump metrics
MarcosNicolau Oct 23, 2024
6670953
separate retries into separate functions
PatStiles Oct 23, 2024
776dc25
abstract retries in avs subscriber
PatStiles Oct 23, 2024
959694b
refactor: wait for transaction receipt
MarcosNicolau Oct 23, 2024
c875e4b
save
PatStiles Oct 23, 2024
9eef24f
reafactor: receipt timeout constant
MarcosNicolau Oct 23, 2024
053d1fb
test: connection retries
MarcosNicolau Oct 23, 2024
24a96ff
docs: typo in retry test [skip ci]
MarcosNicolau Oct 23, 2024
eecf2a4
reorg
PatStiles Oct 24, 2024
d51a16c
export aggregator package
PatStiles Oct 24, 2024
e1fa684
modify main
PatStiles Oct 24, 2024
25b93b1
add config file for testing
PatStiles Oct 24, 2024
4df06bf
make visibility of retry functions public
PatStiles Oct 24, 2024
21ca36b
finish mocks for the rest of the tests
PatStiles Oct 24, 2024
347f155
add missing retry
PatStiles Oct 24, 2024
330c49b
test accept aggregator init function
PatStiles Oct 24, 2024
f0e58cf
fix: permanent err in send aggregator
MarcosNicolau Oct 25, 2024
8550675
progress
PatStiles Oct 25, 2024
e5de508
test fixes
PatStiles Oct 28, 2024
b40f5a0
Comment out aggregator tests as they panic due to known error in eige…
PatStiles Oct 28, 2024
2b25d45
fix: address review comments
MarcosNicolau Oct 29, 2024
696781b
save progress
PatStiles Oct 29, 2024
3258209
refactor: defined constants and better comments
MarcosNicolau Nov 4, 2024
b1bc71f
style: eol grafana .json
MarcosNicolau Nov 4, 2024
7c4c9ad
Merge branch 'staging' into 311-aggregator-wait-for-receipt-for-1-min…
MarcosNicolau Nov 4, 2024
3614696
test: eth utils CalculateGasPriceBumpBasedOnRetry
MarcosNicolau Nov 5, 2024
bcf5456
add transient errors + use struct capture in retry functions
PatStiles Nov 5, 2024
b1b5769
add tests
PatStiles Nov 5, 2024
b706fbf
rm unneeded cmts
PatStiles Nov 5, 2024
280e6c4
refactor ProcessNewSignature
PatStiles Nov 5, 2024
3d3d243
ci: fix
MarcosNicolau Nov 5, 2024
251cd39
cmt in server
PatStiles Nov 6, 2024
aa39199
lint
PatStiles Nov 6, 2024
4648327
Merge branch 'staging' into feat/aggregator_retries
PatStiles Nov 6, 2024
2b67707
Merge branch 'staging' into feat/aggregator_retries
PatStiles Nov 6, 2024
9fa785c
fix merge change
PatStiles Nov 6, 2024
2392c20
add attribution comment
PatStiles Nov 6, 2024
2d5cc86
add maxInterval as option
PatStiles Nov 6, 2024
035f19a
add maxInterval option
PatStiles Nov 6, 2024
97fac6a
remove unused i variable
PatStiles Nov 6, 2024
2bf4a48
refactor to add permanent backoff conversion function + add panic cat…
PatStiles Nov 6, 2024
801f9ed
rm unneeded comments
PatStiles Nov 6, 2024
ca2da62
fix parameters for BalanceAt test
PatStiles Nov 6, 2024
7aff569
add comment
PatStiles Nov 6, 2024
64705f3
nits
PatStiles Nov 6, 2024
0b338d7
remove logs
PatStiles Nov 6, 2024
88a2215
rm "not found" from unneeded functions
PatStiles Nov 6, 2024
2191bfc
Merge branch 'feat/aggregator_retries' into 311-aggregator-wait-for-r…
MarcosNicolau Nov 6, 2024
6ead6ed
rename connections to retry
PatStiles Nov 7, 2024
b8bf783
remove not found error for ProcessNewSignature
PatStiles Nov 7, 2024
2e67ccb
import retry functions from avs writer
PatStiles Nov 7, 2024
3c437ec
import retry functions in avs subscriber + only log success once
PatStiles Nov 7, 2024
718c343
add retryable module to chainio
PatStiles Nov 7, 2024
920e8e4
rm comment + change permanent to transient error
PatStiles Nov 7, 2024
ccc386b
add MaxInterval parameter
PatStiles Nov 7, 2024
71a074d
Remove Transient error type
PatStiles Nov 7, 2024
385bba3
nits for retry test with Transient error
PatStiles Nov 7, 2024
f2d7d81
remove capture var
PatStiles Nov 7, 2024
25cbbd8
feat: bump only when timeout paased
MarcosNicolau Nov 7, 2024
d657099
use time.duration for maxElapsedTime
PatStiles Nov 7, 2024
a6c9541
Merge branch 'feat/aggregator_retries' into 311-aggregator-wait-for-r…
MarcosNicolau Nov 7, 2024
3fde22c
Merge branch 'feat/aggregator_retries' into 311-aggregator-wait-for-r…
MarcosNicolau Nov 7, 2024
332ae57
fix: removed the fallback rpc node accidentally
PatStiles Nov 7, 2024
d92f391
feat: timer to waitTrasactionReceipt
MarcosNicolau Nov 7, 2024
318526f
feat: move constants to config file
MarcosNicolau Nov 7, 2024
ce8dcd0
fix: bump fee 10% if gas price decreased from prev bumped gas price
MarcosNicolau Nov 7, 2024
8d116c7
pass retryable functoin params explicitly from the calling function
PatStiles Nov 7, 2024
bbe16b2
fix: go ci
MarcosNicolau Nov 7, 2024
320821a
fix: go ci
MarcosNicolau Nov 7, 2024
9767536
fix: go ci
MarcosNicolau Nov 7, 2024
d1c17e1
use duration in retry function
PatStiles Nov 8, 2024
84055b5
add retry logic to getTaskIndex + remove test comments
PatStiles Nov 8, 2024
bc63ef9
test comment nits
PatStiles Nov 8, 2024
57090da
emit refactor unit tests
PatStiles Nov 8, 2024
103eace
add permanent error for revert in RespondToTaskV2
PatStiles Nov 8, 2024
7edc6bb
rm cmt values for aggregator test yaml
PatStiles Nov 8, 2024
eaf405b
feat: bump gas price traces
MarcosNicolau Nov 8, 2024
525001c
fix: permanent errs only when tx reverted
MarcosNicolau Nov 8, 2024
7bfca75
add make target + add unit tests to ci
PatStiles Nov 8, 2024
4eb7ba8
add foundry to ci
PatStiles Nov 8, 2024
d2f8d2d
refactor: use respond to task retryabale
MarcosNicolau Nov 8, 2024
550c9c2
change retry function names
PatStiles Nov 8, 2024
b30d1ce
rename InitializeNewTaskRetryable to InitializeNewTask
PatStiles Nov 8, 2024
0345248
add Retryable back to function names
PatStiles Nov 9, 2024
67f59dd
refactor: tracing and docs
MarcosNicolau Nov 11, 2024
18f77bb
chore: adjust bump percentages
MarcosNicolau Nov 11, 2024
509f6ef
fix: telemetry bump gas price endpoint
MarcosNicolau Nov 11, 2024
daa8f40
refactor: get gas price retryable
MarcosNicolau Nov 11, 2024
6051a57
refactor: address review comments
MarcosNicolau Nov 11, 2024
5adf099
chore: config-aggregator comments
MarcosNicolau Nov 11, 2024
94aec13
Merge branch 'feat/aggregator_retries' into 311-aggregator-wait-for-r…
MarcosNicolau Nov 11, 2024
ba7e75d
comments + adjust retry params for contract calls + add permanent errors
PatStiles Nov 11, 2024
03398a1
fix: CI test go retries
uri-99 Nov 11, 2024
5c02e1d
fix: run make test on build and test go ci
uri-99 Nov 11, 2024
8080f5e
Merge branch 'staging' into feat/aggregator_retries
uri-99 Nov 11, 2024
c2acff6
remove permanent erros for ProcessNewSignature + comment
PatStiles Nov 11, 2024
bb89e05
adjust timeout for retry tests
PatStiles Nov 11, 2024
0c47ec2
add back in signature process failure for ProcessNewSignature
PatStiles Nov 11, 2024
45a0c4d
add anvil to make test
PatStiles Nov 11, 2024
823ccf1
add documentation nits
PatStiles Nov 11, 2024
2a17a15
adjust timeout in go test for make test
PatStiles Nov 11, 2024
d12706b
Merge branch 'feat/aggregator_retries' into 311-aggregator-wait-for-r…
MarcosNicolau Nov 11, 2024
0bef69f
Merge remote-tracking branch 'origin/staging' into 311-aggregator-wai…
MarcosNicolau Nov 12, 2024
7847bc2
style: fmt yaml
MarcosNicolau Nov 12, 2024
c515681
fix: dashboards
avilagaston9 Nov 12, 2024
475125d
refactor: wait timeouts
MarcosNicolau Nov 12, 2024
0c46f52
style: fmt
MarcosNicolau Nov 12, 2024
5b1219a
refactor: address review comments
MarcosNicolau Nov 13, 2024
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
10 changes: 2 additions & 8 deletions aggregator/internal/pkg/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ func (agg *Aggregator) sendAggregatedResponse(batchIdentifierHash [32]byte, batc
"senderAddress", hex.EncodeToString(senderAddress[:]),
"batchIdentifierHash", hex.EncodeToString(batchIdentifierHash[:]))

txHash, err := agg.avsWriter.SendAggregatedResponse(batchIdentifierHash, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
onRetry := func() { agg.metrics.IncBumpedGasPriceForAggregatedResponse() }
receipt, err := agg.avsWriter.SendAggregatedResponse(batchIdentifierHash, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature, onRetry)
if err != nil {
agg.walletMutex.Unlock()
agg.logger.Infof("- Unlocked Wallet Resources: Error sending aggregated response for batch %s. Error: %s", hex.EncodeToString(batchIdentifierHash[:]), err)
Expand All @@ -315,13 +316,6 @@ func (agg *Aggregator) sendAggregatedResponse(batchIdentifierHash [32]byte, batc
agg.walletMutex.Unlock()
agg.logger.Infof("- Unlocked Wallet Resources: Sending aggregated response for batch %s", hex.EncodeToString(batchIdentifierHash[:]))

receipt, err := utils.WaitForTransactionReceipt(
agg.AggregatorConfig.BaseConfig.EthRpcClient, context.Background(), *txHash)
if err != nil {
agg.telemetry.LogTaskError(batchMerkleRoot, err)
return nil, err
}

agg.metrics.IncAggregatedResponses()

return receipt, nil
Expand Down
73 changes: 63 additions & 10 deletions core/chainio/avs_writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
servicemanager "github.com/yetanotherco/aligned_layer/contracts/bindings/AlignedLayerServiceManager"
connection "github.com/yetanotherco/aligned_layer/core"
"github.com/yetanotherco/aligned_layer/core/config"
"github.com/yetanotherco/aligned_layer/core/utils"
)

const (
GasBumpPercentage int = 20
// wait as much as 3 blocks time for the receipt
SendAggregateResponseReceiptTimeout time.Duration = time.Second * 36
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
)

type AvsWriter struct {
Expand Down Expand Up @@ -70,10 +78,15 @@ func NewAvsWriterFromConfig(baseConfig *config.BaseConfig, ecdsaConfig *config.E
}, nil
}

func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMerkleRoot [32]byte, senderAddress [20]byte, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature) (*common.Hash, error) {
// Sends AggregatedResponse and waits for the receipt for three blocks, if not received
// it will try again bumping the last tx gas price based on `CalculateGasPriceBump`
// This process happens indefinitely until the transaction is included.
Comment on lines +75 to +77
Copy link
Collaborator

@avilagaston9 avilagaston9 Nov 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe for a separate PR, but we need to add some numbers to graph the retry logic. See:

pub async fn cancel_create_new_task_tx(&self, old_tx_gas_price: U256) {

// Note: If the rpc endpoints fail, the retry will stop, as it will infinitely try
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMerkleRoot [32]byte, senderAddress [20]byte, nonSignerStakesAndSignature servicemanager.IBLSSignatureCheckerNonSignerStakesAndSignature, onRetry func()) (*types.Receipt, error) {
txOpts := *w.Signer.GetTxOpts()
txOpts.NoSend = true // simulate the transaction
tx, err := w.AvsContractBindings.ServiceManager.RespondToTaskV2(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)

if err != nil {
// Retry with fallback
tx, err = w.AvsContractBindings.ServiceManagerFallback.RespondToTaskV2(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
Expand All @@ -87,21 +100,61 @@ func (w *AvsWriter) SendAggregatedResponse(batchIdentifierHash [32]byte, batchMe
return nil, err
}

// Send the transaction
// Set the nonce, as we might have to replace the transaction with a higher fee
txNonce := new(big.Int).SetUint64(tx.Nonce())
txOpts.NoSend = false
txOpts.GasLimit = tx.Gas() * 110 / 100 // Add 10% to the gas limit
tx, err = w.AvsContractBindings.ServiceManager.RespondToTaskV2(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
if err != nil {
// Retry with fallback
tx, err = w.AvsContractBindings.ServiceManagerFallback.RespondToTaskV2(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
txOpts.Nonce = txNonce

i := 0
JuArce marked this conversation as resolved.
Show resolved Hide resolved
sendTransaction := func() (*types.Receipt, error) {
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
if i > 0 {
onRetry()
}
i++

// get gas price
gasPrice, err := w.Client.SuggestGasPrice(context.Background())
uri-99 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
// Retry with fallback
gasPrice, err = w.ClientFallback.SuggestGasPrice(context.Background())
if err != nil {
return nil, fmt.Errorf("transaction simulation failed: %v", err)
}
}
txOpts.GasPrice = utils.CalculateGasPriceBumpBasedOnRetry(gasPrice, GasBumpPercentage, i)

w.logger.Infof("Sending ResponseToTask transaction with a gas price of %v", txOpts.GasPrice)
err = w.checkRespondToTaskFeeLimit(tx, txOpts, batchIdentifierHash, senderAddress)

JuArce marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, connection.PermanentError{Inner: err}
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
}

tx, err = w.AvsContractBindings.ServiceManager.RespondToTaskV2(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
if err != nil {
// Retry with fallback
tx, err = w.AvsContractBindings.ServiceManagerFallback.RespondToTaskV2(&txOpts, batchMerkleRoot, senderAddress, nonSignerStakesAndSignature)
if err != nil {
return nil, connection.PermanentError{Inner: err}
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
}
}

ctx, cancel := context.WithTimeout(context.Background(), SendAggregateResponseReceiptTimeout)
defer cancel()
uri-99 marked this conversation as resolved.
Show resolved Hide resolved
receipt, err := utils.WaitForTransactionReceipt(w.Client, ctx, tx.Hash())

if receipt != nil {
return receipt, nil
}
// if we are here, this means we have reached the timeout (after three blocks it hasn't been included)
// so we try again by bumping the fee to make sure its included
if err != nil {
return nil, err
}
return nil, fmt.Errorf("transaction failed")
}
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved

txHash := tx.Hash()

return &txHash, nil
return connection.RetryWithData(sendTransaction, 1000, 2, 0)
}

func (w *AvsWriter) checkRespondToTaskFeeLimit(tx *types.Transaction, txOpts bind.TransactOpts, batchIdentifierHash [32]byte, senderAddress [20]byte) error {
Expand Down
77 changes: 77 additions & 0 deletions core/connection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package connection

import (
"time"

"github.com/cenkalti/backoff/v4"
)

type PermanentError struct {
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
Inner error
}

func (e PermanentError) Error() string { return e.Inner.Error() }
func (e PermanentError) Unwrap() error {
return e.Inner
}
func (e PermanentError) Is(err error) bool {
_, ok := err.(PermanentError)
return ok
}

// Same as Retry only that the functionToRetry can return a value upon correct execution
func RetryWithData[T any](functionToRetry func() (*T, error), minDelay uint64, factor float64, maxTries uint64) (*T, error) {
JuArce marked this conversation as resolved.
Show resolved Hide resolved
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
f := func() (*T, error) {
val, err := functionToRetry()
if perm, ok := err.(PermanentError); err != nil && ok {
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
return nil, backoff.Permanent(perm.Inner)
}
return val, err
}

randomOption := backoff.WithRandomizationFactor(0)

initialRetryOption := backoff.WithInitialInterval(time.Millisecond * time.Duration(minDelay))
multiplierOption := backoff.WithMultiplier(factor)
expBackoff := backoff.NewExponentialBackOff(randomOption, multiplierOption, initialRetryOption)
var maxRetriesBackoff backoff.BackOff

if maxTries > 0 {
maxRetriesBackoff = backoff.WithMaxRetries(expBackoff, maxTries)
} else {
maxRetriesBackoff = expBackoff
}

return backoff.RetryWithData(f, maxRetriesBackoff)
}

// Retries a given function in an exponential backoff manner.
// It will retry calling the function while it returns an error, until the max retries.
// If maxTries == 0 then the retry function will run indefinitely until success
// from the configuration are reached, or until a `PermanentError` is returned.
// The function to be retried should return `PermanentError` when the condition for stop retrying
// is met.
func Retry(functionToRetry func() error, minDelay uint64, factor float64, maxTries uint64) error {
f := func() error {
err := functionToRetry()
if perm, ok := err.(PermanentError); err != nil && ok {
return backoff.Permanent(perm.Inner)
}
return err
}

randomOption := backoff.WithRandomizationFactor(0)

initialRetryOption := backoff.WithInitialInterval(time.Millisecond * time.Duration(minDelay))
multiplierOption := backoff.WithMultiplier(factor)
expBackoff := backoff.NewExponentialBackOff(randomOption, multiplierOption, initialRetryOption)
var maxRetriesBackoff backoff.BackOff

if maxTries > 0 {
maxRetriesBackoff = backoff.WithMaxRetries(expBackoff, maxTries)
} else {
maxRetriesBackoff = expBackoff
}

return backoff.Retry(f, maxRetriesBackoff)
}
81 changes: 81 additions & 0 deletions core/connection_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package connection_test

import (
"fmt"
"testing"

connection "github.com/yetanotherco/aligned_layer/core"
)

func DummyFunction(x uint64) (uint64, error) {
fmt.Println("Doing some work...")
if x == 42 {
return 0, connection.PermanentError{Inner: fmt.Errorf("Permanent error!")}
} else if x < 42 {
return 0, fmt.Errorf("Transient error!")
}
return x, nil
}

// here we run the dummy function and with the retry and check:
// - The number of retries checks based on the `n`
// - The returned valued matches based on the `n`
// - The returned err matches based on the `n`
func TestRetryWithData(t *testing.T) {
retries := -1
testFun := func(n uint64) func() (*uint64, error) {
return func() (*uint64, error) {
retries++
x, err := DummyFunction(n)
return &x, err
}
}
data, err := connection.RetryWithData(testFun(uint64(41)), 1000, 2, 3)
if !(retries == 3 && *data == 0 && err != nil) {
t.Error("Incorrect execution when n == 41")
}
//restart
retries = -1
data, err = connection.RetryWithData(testFun(42), 1000, 2, 3)
if !(retries == 0 && data == nil) {
if _, ok := err.(*connection.PermanentError); ok {
t.Error("Incorrect execution when n == 42")
}
}
//restart
retries = -1
data, err = connection.RetryWithData(testFun(43), 1000, 2, 3)
if !(retries == 0 && *data == 43 && err == nil) {
t.Error("Incorrect execution when n == 43")
}
}

// same as above but without checking returned data
func TestRetry(t *testing.T) {
retries := -1
testFun := func(n uint64) func() error {
return func() error {
retries++
_, err := DummyFunction(n)
return err
}
}
err := connection.Retry(testFun(uint64(41)), 1000, 2, 3)
if !(retries == 3 && err != nil) {
t.Error("Incorrect execution when n == 41")
}
//restart
retries = -1
err = connection.Retry(testFun(42), 1000, 2, 3)
if !(retries == 0) {
if _, ok := err.(*connection.PermanentError); ok {
t.Error("Incorrect execution when n == 42")
}
}
//restart
retries = -1
err = connection.Retry(testFun(43), 1000, 2, 3)
if !(retries == 0 && err == nil) {
t.Error("Incorrect execution when n == 43")
}
}
25 changes: 21 additions & 4 deletions core/utils/eth_client_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package utils

import (
"context"
"math/big"
"time"

"fmt"
Expand All @@ -17,12 +18,16 @@ const sleepTime = 5 * time.Second

func WaitForTransactionReceipt(client eth.InstrumentedClient, ctx context.Context, txHash gethcommon.Hash) (*types.Receipt, error) {
for i := 0; i < maxRetries; i++ {
receipt, err := client.TransactionReceipt(ctx, txHash)
if err != nil {
time.Sleep(sleepTime)
} else {
receipt, _ := client.TransactionReceipt(ctx, txHash)
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
if receipt != nil {
return receipt, nil
}
// if context has timed out, return
if ctx.Err() != nil {
return nil, ctx.Err()
} else {
time.Sleep(sleepTime)
}
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
}
return nil, fmt.Errorf("transaction receipt not found for txHash: %s", txHash.String())
}
Expand All @@ -42,3 +47,15 @@ func BytesToQuorumThresholdPercentages(quorumThresholdPercentagesBytes []byte) e
}
return quorumThresholdPercentages
}

// Very basic algorithm to calculate the gasPrice bump based on the currentGasPrice a constant percentage and the retry number.
JuArce marked this conversation as resolved.
Show resolved Hide resolved
// It adds a the percentage to the current gas price and a 5% * i, where i is the iteration number. That is:
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
func CalculateGasPriceBumpBasedOnRetry(currentGasPrice *big.Int, percentage int, i int) *big.Int {
retryPercentage := new(big.Int).Mul(big.NewInt(5), big.NewInt(int64(i)))
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved
percentageBump := new(big.Int).Add(big.NewInt(int64(percentage)), retryPercentage)
bumpAmount := new(big.Int).Mul(currentGasPrice, percentageBump)
bumpAmount = new(big.Int).Div(bumpAmount, big.NewInt(100))
bumpedGasPrice := new(big.Int).Add(currentGasPrice, bumpAmount)
MarcosNicolau marked this conversation as resolved.
Show resolved Hide resolved

return bumpedGasPrice
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (

require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6
github.com/cenkalti/backoff/v4 v4.3.0
github.com/consensys/gnark v0.10.0
github.com/consensys/gnark-crypto v0.12.2-0.20240215234832-d72fcb379d3e
github.com/fxamacker/cbor/v2 v2.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurT
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
Expand Down
Loading
Loading