Skip to content

Commit

Permalink
fee mgmt + apiAdapter fix/refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
xmariachi committed Nov 30, 2024
1 parent 10561e6 commit 484b272
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 40 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ALLORA_OFFCHAIN_NODE_CONFIG_JSON='{"wallet":{"addressKeyName":"test-offchain","addressRestoreMnemonic":"surge verify input...","alloraHomeDir":"","gas":"auto","gasAdjustment":1.5,"gasPrices":0.08,"maxFees":200000,"nodeRpc":"http://localhost:26657","maxRetries":3,"retryDelay":3,"accountSequenceRetryDelay":5,"submitTx":true,"blockDurationEstimated":10,"windowCorrectionFactor":0.8},"worker":[{"topicId":1,"inferenceEntrypointName":"api-worker-reputer","loopSeconds":5,"parameters":{"InferenceEndpoint":"http://localhost:8000/inference/{Token}","Token":"ETH"}}]}'
ALLORA_OFFCHAIN_NODE_CONFIG_JSON='{"wallet":{"addressKeyName":"test-offchain","addressRestoreMnemonic":"surge verify input...","alloraHomeDir":"","gas":"auto","gasAdjustment":1.2,"gasPrices":"auto","maxFees":500000,"nodeRpc":"http://localhost:26657","maxRetries":3,"retryDelay":3,"accountSequenceRetryDelay":5,"submitTx":true,"blockDurationEstimated":10,"windowCorrectionFactor":0.8},"worker":[{"topicId":1,"inferenceEntrypointName":"api-worker-reputer","loopSeconds":5,"parameters":{"InferenceEndpoint":"http://localhost:8000/inference/{Token}","Token":"ETH"}}]}'
29 changes: 12 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ The wallet configuration is done in `config.json` under the `wallet` field.

- `gas` can be set to `auto` or a specific gas value. If set to `auto`, the node will automatically calculate the gas limit based on the estimated gas used by the transactions.
- `gasAdjustment` is used to adjust the gas limit.
- `gasPrices` and `maxFees` fields are used to set the gas prices and max fees for the wallet. They are expressed in `uallo`.
- `gasPrices` can be set to `auto` or a specific gas price. If set to `auto`, the node will automatically calculate the gas price based on chain's feemarket-based gas prices. This is the recommended setting, since feemarket introduces variability in the gas price in the chain.
- `maxFees` set the max fees that can be paid for a transaction. They are expressed numerically in `uallo`.

### Error handling

Expand Down Expand Up @@ -184,8 +185,7 @@ These below are excerpts of the configuration (with some parts omitted for brevi
"worker": [
{
"topicId": 1,
"inferenceEntrypointName": "api-worker-reputer",
"loopSeconds": 10,
"inferenceEntrypointName": "apiAdapter",
"parameters": {
"InferenceEndpoint": "http://source:8000/inference/{Token}",
"Token": "ETH"
Expand All @@ -201,8 +201,7 @@ These below are excerpts of the configuration (with some parts omitted for brevi
"worker": [
{
"topicId": 1,
"forecastEntrypointName": "api-worker-reputer",
"loopSeconds": 10,
"forecastEntrypointName": "apiAdapter",
"parameters": {
"ForecastEndpoint": "http://source:8000/forecasts/{TopicId}/{BlockHeight}"
}
Expand All @@ -219,9 +218,8 @@ These below are excerpts of the configuration (with some parts omitted for brevi
"worker": [
{
"topicId": 1,
"inferenceEntrypointName": "api-worker-reputer",
"forecastEntrypointName": "api-worker-reputer",
"loopSeconds": 10,
"inferenceEntrypointName": "apiAdapter",
"forecastEntrypointName": "apiAdapter",
"parameters": {
"InferenceEndpoint": "http://source:8000/inference/{Token}",
"ForecastEndpoint": "http://source:8000/forecasts/{TopicId}/{BlockHeight}",
Expand All @@ -239,9 +237,8 @@ These below are excerpts of the configuration (with some parts omitted for brevi
"reputer": [
{
"topicId": 1,
"groundTruthEntrypointName": "api-worker-reputer",
"lossFunctionEntrypointName": "api-worker-reputer",
"loopSeconds": 30,
"groundTruthEntrypointName": "apiAdapter",
"lossFunctionEntrypointName": "apiAdapter",
"minStake": 100000,
"groundTruthParameters": {
"GroundTruthEndpoint": "http://localhost:8888/gt/{Token}/{BlockHeight}",
Expand All @@ -265,9 +262,8 @@ These below are excerpts of the configuration (with some parts omitted for brevi
"worker": [
{
"topicId": 1,
"inferenceEntrypointName": "api-worker-reputer",
"forecastEntrypointName": "api-worker-reputer",
"loopSeconds": 10,
"inferenceEntrypointName": "apiAdapter",
"forecastEntrypointName": "apiAdapter",
"parameters": {
"InferenceEndpoint": "http://source:8000/inference/{Token}",
"ForecastEndpoint": "http://source:8000/forecasts/{TopicId}/{BlockHeight}",
Expand All @@ -278,9 +274,8 @@ These below are excerpts of the configuration (with some parts omitted for brevi
"reputer": [
{
"topicId": 1,
"groundTruthEntrypointName": "api-worker-reputer",
"lossFunctionEntrypointName": "api-worker-reputer",
"loopSeconds": 30,
"groundTruthEntrypointName": "apiAdapter",
"lossFunctionEntrypointName": "apiAdapter",
"minStake": 100000,
"groundTruthParameters": {
"GroundTruthEndpoint": "http://localhost:8888/gt/{Token}/{BlockHeight}",
Expand Down
4 changes: 2 additions & 2 deletions adapter/api/apiadapter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ Example as Reputer ("gt" in this context means "ground truth"):
Reputer: []lib.ReputerConfig{
{
"topicId": 1,
"groundTruthEntrypointName": "api-worker-reputer",
"lossFunctionEntrypointName": "api-worker-reputer",
"groundTruthEntrypointName": "apiAdapter",
"lossFunctionEntrypointName": "apiAdapter",
"loopSeconds": 30,
"minStake": 100000,
"groundTruthParameters": {
Expand Down
2 changes: 1 addition & 1 deletion adapter/api/apiadapter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ func (a *AlloraAdapter) CanSourceGroundTruthAndComputeLoss() bool {

func NewAlloraAdapter() *AlloraAdapter {
return &AlloraAdapter{
name: "api-worker-reputer",
name: "apiAdapter",
}
}

Expand Down
6 changes: 3 additions & 3 deletions adapter_factory.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package main

import (
apiAdapter "allora_offchain_node/adapter/api/apiadapter"
apiadapter "allora_offchain_node/adapter/api/apiadapter"
lib "allora_offchain_node/lib"
"fmt"
)

func NewAlloraAdapter(name string) (lib.AlloraAdapter, error) {
switch name {
case "api-worker-reputer":
return apiAdapter.NewAlloraAdapter(), nil
case "apiAdapter":
return apiadapter.NewAlloraAdapter(), nil
// Add other cases for different adapters here
default:
return nil, fmt.Errorf("unknown adapter name: %s", name)
Expand Down
10 changes: 5 additions & 5 deletions config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"addressRestoreMnemonic": "your mnemonic here",
"alloraHomeDir": "",
"gas": "auto",
"gasAdjustment": 1.5,
"gasAdjustment": 1.2,
"gasPrices": "auto",
"maxFees": 2000000,
"maxFees": 500000,
"nodeRpc": "https://allora-rpc.testnet.allora.network",
"maxRetries": 5,
"retryDelay": 3,
Expand All @@ -18,7 +18,7 @@
"worker": [
{
"topicId": 1,
"inferenceEntrypointName": "api-worker-reputer",
"inferenceEntrypointName": "apiAdapter",
"parameters": {
"InferenceEndpoint": "http://source:8000/inference/{Token}",
"Token": "ETH"
Expand All @@ -28,8 +28,8 @@
"reputer": [
{
"topicId": 1,
"groundTruthEntrypointName": "api-worker-reputer",
"lossFunctionEntrypointName": "api-worker-reputer",
"groundTruthEntrypointName": "apiAdapter",
"lossFunctionEntrypointName": "apiAdapter",
"minStake": 100000,
"groundTruthParameters": {
"GroundTruthEndpoint": "http://localhost:8888/gt/{Token}/{BlockHeight}",
Expand Down
18 changes: 13 additions & 5 deletions lib/repo_tx_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,16 @@ func processError(err error, infoMsg string, retryCount int64, node *NodeConfig)
time.Sleep(time.Duration(node.Wallet.AccountSequenceRetryDelay) * time.Second)
return ERROR_PROCESSING_CONTINUE, nil
case int(sdkerrors.ErrInsufficientFee.ABCICode()):
log.Info().
Err(err).
Str("msg", infoMsg).
Msg("Insufficient fees")
return ERROR_PROCESSING_FEES, nil
case int(feemarkettypes.ErrNoFeeCoins.ABCICode()):
log.Info().
Err(err).
Str("msg", infoMsg).
Msg("No fee coins")
return ERROR_PROCESSING_FEES, nil
case int(sdkerrors.ErrTxTooLarge.ABCICode()):
return ERROR_PROCESSING_ERROR, errorsmod.Wrapf(err, "tx too large")
Expand Down Expand Up @@ -166,7 +174,7 @@ func (node *NodeConfig) SendDataWithRetry(ctx context.Context, req sdktypes.Msg,
}
excessFactorFees := float64(EXCESS_CORRECTION_IN_GAS) * gasPrices
// Keep track of how many times fees need to be recalculated to avoid missing fee info between errors
recalculateFees := 0
recalculateFees := 1
// Use to keep track of expected sequence number between errors
globalExpectedSeqNum := uint64(0)

Expand All @@ -178,7 +186,7 @@ func (node *NodeConfig) SendDataWithRetry(ctx context.Context, req sdktypes.Msg,

for retryCount := int64(0); retryCount <= node.Wallet.MaxRetries; retryCount++ {
log.Debug().Msgf("SendDataWithRetry iteration started (%d/%d)", retryCount, node.Wallet.MaxRetries)
// Create tx without fees
// Create tx without fees to simulate tx creation and get estimated gas and seq number
txOptions := cosmosclient.TxOptions{} // nolint: exhaustruct
if globalExpectedSeqNum > 0 && node.Chain.Client.TxFactory.Sequence() != globalExpectedSeqNum {
log.Debug().
Expand Down Expand Up @@ -228,7 +236,6 @@ func (node *NodeConfig) SendDataWithRetry(ctx context.Context, req sdktypes.Msg,
case ERROR_PROCESSING_FEES:
// Error has not been handled, just mark as recalculate fees on this iteration
log.Debug().Msg("Marking fee recalculation on tx creation")
recalculateFees += 1
case ERROR_PROCESSING_FAILURE:
return nil, errorsmod.Wrapf(err, "tx failed and not retried")
default:
Expand All @@ -240,9 +247,10 @@ func (node *NodeConfig) SendDataWithRetry(ctx context.Context, req sdktypes.Msg,
}

// Handle fees if necessary
if gasPrices > 0 && recalculateFees > 0 {
if gasPrices > 0 {
// Precalculate fees
fees := uint64(float64(txService.Gas()+EXCESS_CORRECTION_IN_GAS) * gasPrices)
estimatedGas := float64(txService.Gas()) * node.Wallet.GasAdjustment
fees := uint64(float64(estimatedGas+EXCESS_CORRECTION_IN_GAS) * gasPrices)
// Add excess fees correction factor to increase with each fee-problematic retry
fees = fees + uint64(float64(recalculateFees)*excessFactorFees)
// Limit fees to maxFees
Expand Down
12 changes: 6 additions & 6 deletions usecase/build_commit_worker_payload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ func TestComputeWorkerBundle(t *testing.T) {
workerConfig: lib.WorkerResponse{
WorkerConfig: lib.WorkerConfig{
TopicId: emissionstypes.TopicId(1),
InferenceEntrypointName: "api-worker-reputer",
ForecastEntrypointName: "api-worker-reputer",
InferenceEntrypointName: "apiAdapter",
ForecastEntrypointName: "apiAdapter",
InferenceEntrypoint: nil, // Will be set in the test
ForecastEntrypoint: nil, // Will be set in the test
Parameters: workerOptions,
Expand Down Expand Up @@ -75,8 +75,8 @@ func TestComputeWorkerBundle(t *testing.T) {
workerConfig: lib.WorkerResponse{
WorkerConfig: lib.WorkerConfig{
TopicId: emissionstypes.TopicId(1),
InferenceEntrypointName: "api-worker-reputer",
ForecastEntrypointName: "api-worker-reputer",
InferenceEntrypointName: "apiAdapter",
ForecastEntrypointName: "apiAdapter",
InferenceEntrypoint: nil,
ForecastEntrypoint: nil,
Parameters: workerOptions,
Expand All @@ -96,8 +96,8 @@ func TestComputeWorkerBundle(t *testing.T) {
workerConfig: lib.WorkerResponse{
WorkerConfig: lib.WorkerConfig{
TopicId: emissionstypes.TopicId(1),
InferenceEntrypointName: "api-worker-reputer",
ForecastEntrypointName: "api-worker-reputer",
InferenceEntrypointName: "apiAdapter",
ForecastEntrypointName: "apiAdapter",
InferenceEntrypoint: nil,
ForecastEntrypoint: nil,
Parameters: workerOptions,
Expand Down

0 comments on commit 484b272

Please sign in to comment.