Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 401
feat: aggregator bump fee if transaction was not included#1286
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ba9112a42b4ed3896b98cdceaa0a61a64df6873cbeb5bf04e8bfd3369cb6780262765990c429010597b0dbc7d60cc9b765bf7dad572db766ecaf6004c2f00d9e53e5627c8cc65fa0a282ec553b34a80cc99aa094b614916527489b5abc31e6f85dda96f2ace3469101001eeab04375dd7d8660b529fbe430a053d071172b21b5e2a8e10a7eb1453b26670953776dc25959694bc875e4b9eef24f053d1fb24a96ffeecf2a4d51a16ce1fa68425b93b14df06bf21ca36b347f155330c49bf0e58cf8550675e5de508b40f5a02b25d45696781b3258209b1bc71f7c4c9ad3614696bcf5456b1b5769b706fbf280e6c43d3d243251cd39aa3919946483272b677079fa785c2392c202d5cc86035f19a97fac6a2bf4a48801f9edca2da627aff56964705f30b338d788a22152191bfc6ead6edb8bf7832e67ccb3c437ec718c343920e8e4ccc386b71a074d385bba3f2d7d8125cbbd8d657099a6c95413fde22c332ae57d92f391318526fce8dcd08d116c7bbe16b2320821a9767536d1c17e184055b5bc63ef957090da103eace7edc6bbeaf405b525001c7bfca754eb7ba8d2f8d2d550c9c2b30d1ce034524867f59dd18f77bb509f6efdaa8f406051a575adf09994aec13ba7e75d03398a15c02e1d8080f5ec2acff6bb89e050c47ec245a0c4d823ccf12a17a15d12706b0bef69f7847bc2c515681475125d0c46f525b1219aFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -15,7 +15,9 @@ import ( | ||||
| "github.com/ethereum/go-ethereum/common" | ||||
| "github.com/ethereum/go-ethereum/core/types" | ||||
| servicemanager "github.com/yetanotherco/aligned_layer/contracts/bindings/AlignedLayerServiceManager" | ||||
| retry "github.com/yetanotherco/aligned_layer/core" | ||||
| "github.com/yetanotherco/aligned_layer/core/config" | ||||
| "github.com/yetanotherco/aligned_layer/core/utils" | ||||
| ) | ||||
| type AvsWriter struct { | ||||
| @@ -70,7 +72,10 @@ 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
| ||||
| pubasyncfncancel_create_new_task_tx(&self,old_tx_gas_price:U256){ |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add comments explaining how we are using this function. We are using different bump percentages depending on which price that we are bumping.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -2,6 +2,8 @@ package utils | ||
| import ( | ||
| "context" | ||
| "math/big" | ||
| "time" | ||
| "github.com/Layr-Labs/eigensdk-go/chainio/clients/eth" | ||
| eigentypes "github.com/Layr-Labs/eigensdk-go/types" | ||
| @@ -10,11 +12,25 @@ import ( | ||
| retry "github.com/yetanotherco/aligned_layer/core" | ||
| ) | ||
| func WaitForTransactionReceipt(client eth.InstrumentedClient, ctx context.Context, txHash gethcommon.Hash) (*types.Receipt, error) { | ||
| // WaitForTransactionReceiptRetryable repeatedly attempts to fetch the transaction receipt for a given transaction hash. | ||
| // If the receipt is not found, the function will retry with exponential backoff until the specified `waitTimeout` duration is reached. | ||
| // If the receipt is still unavailable after `waitTimeout`, it will return an error. | ||
| // | ||
| // Note: The `time.Second * 2` is set as the max interval in the retry mechanism because we can't reliably measure the specific time the tx will be included in a block. | ||
| // Setting a higher value will imply doing less retries across the waitTimeout and so we might lose the receipt | ||
| func WaitForTransactionReceiptRetryable(client eth.InstrumentedClient, fallbackClient eth.InstrumentedClient, txHash gethcommon.Hash, waitTimeout time.Duration) (*types.Receipt, error) { | ||
| receipt_func := func() (*types.Receipt, error) { | ||
| return client.TransactionReceipt(ctx, txHash) | ||
| receipt, err := client.TransactionReceipt(context.Background(), txHash) | ||
| if err != nil { | ||
| receipt, err = client.TransactionReceipt(context.Background(), txHash) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return receipt, nil | ||
| } | ||
| return receipt, nil | ||
| } | ||
| return retry.RetryWithData(receipt_func, retry.MinDelay, retry.RetryFactor, retry.NumRetries, retry.MaxInterval, retry.MaxElapsedTime) | ||
| return retry.RetryWithData(receipt_func, retry.MinDelay, retry.RetryFactor, 0, time.Second*2, waitTimeout) | ||
| } | ||
| func BytesToQuorumNumbers(quorumNumbersBytes []byte) eigentypes.QuorumNums { | ||
| @@ -32,3 +48,44 @@ func BytesToQuorumThresholdPercentages(quorumThresholdPercentagesBytes []byte) e | ||
| } | ||
| return quorumThresholdPercentages | ||
| } | ||
| // Simple algorithm to calculate the gasPrice bump based on: | ||
| // the currentGasPrice, a base bump percentage, a retry percentage, and the retry count. | ||
| // Formula: currentGasPrice + (currentGasPrice * (baseBumpPercentage + retryCount * incrementalRetryPercentage) / 100) | ||
MarcosNicolau marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| func CalculateGasPriceBumpBasedOnRetry(currentGasPrice *big.Int, baseBumpPercentage uint, retryAttemptPercentage uint, retryCount int) *big.Int { | ||
| // Incremental percentage increase for each retry attempt (i*retryAttemptPercentage) | ||
| incrementalRetryPercentage := new(big.Int).Mul(big.NewInt(int64(retryAttemptPercentage)), big.NewInt(int64(retryCount))) | ||
| // Total bump percentage: base bump + incremental retry percentage | ||
| totalBumpPercentage := new(big.Int).Add(big.NewInt(int64(baseBumpPercentage)), incrementalRetryPercentage) | ||
| // Calculate the bump amount: currentGasPrice * totalBumpPercentage / 100 | ||
| bumpAmount := new(big.Int).Mul(currentGasPrice, totalBumpPercentage) | ||
| bumpAmount = new(big.Int).Div(bumpAmount, big.NewInt(100)) | ||
| // Final bumped gas price: currentGasPrice + bumpAmount | ||
| bumpedGasPrice := new(big.Int).Add(currentGasPrice, bumpAmount) | ||
| return bumpedGasPrice | ||
| } | ||
| /* | ||
| GetGasPriceRetryable | ||
| Get the gas price from the client with retry logic. | ||
| - All errors are considered Transient Errors | ||
| - Retry times: 1 sec, 2 sec, 4 sec | ||
| */ | ||
| func GetGasPriceRetryable(client eth.InstrumentedClient, fallbackClient eth.InstrumentedClient) (*big.Int, error) { | ||
| respondToTaskV2_func := func() (*big.Int, error) { | ||
| gasPrice, err := client.SuggestGasPrice(context.Background()) | ||
| if err != nil { | ||
| gasPrice, err = fallbackClient.SuggestGasPrice(context.Background()) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| } | ||
| return gasPrice, nil | ||
| } | ||
| return retry.RetryWithData(respondToTaskV2_func, retry.MinDelay, retry.RetryFactor, retry.NumRetries, retry.MaxInterval, retry.MaxElapsedTime) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package utils_test | ||
| import ( | ||
| "math/big" | ||
| "testing" | ||
| "github.com/yetanotherco/aligned_layer/core/utils" | ||
| ) | ||
| func TestCalculateGasPriceBumpBasedOnRetry(t *testing.T) { | ||
| baseBumpPercentage := uint(20) | ||
| incrementalRetryPercentage := uint(5) | ||
| gasPrices := [5]*big.Int{ | ||
| big.NewInt(3000000000), | ||
| big.NewInt(3000000000), | ||
| big.NewInt(4000000000), | ||
| big.NewInt(4000000000), | ||
| big.NewInt(5000000000)} | ||
| expectedBumpedGasPrices := [5]*big.Int{ | ||
| big.NewInt(3600000000), | ||
| big.NewInt(3750000000), | ||
| big.NewInt(5200000000), | ||
| big.NewInt(5400000000), | ||
| big.NewInt(7000000000)} | ||
| for i := 0; i < len(gasPrices); i++ { | ||
| currentGasPrice := gasPrices[i] | ||
| bumpedGasPrice := utils.CalculateGasPriceBumpBasedOnRetry(currentGasPrice, baseBumpPercentage, incrementalRetryPercentage, i) | ||
| expectedGasPrice := expectedBumpedGasPrices[i] | ||
| if bumpedGasPrice.Cmp(expectedGasPrice) != 0 { | ||
| t.Errorf("Bumped gas price does not match expected gas price, expected value %v, got: %v", expectedGasPrice, bumpedGasPrice) | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.