Skip to content

Commit

Permalink
feat: support fixed gas for vote and prevote transactions (#337)
Browse files Browse the repository at this point in the history
* feat: support fixed gas for vote and prevote transactions

* update config

* changelog
  • Loading branch information
robert-zaremba authored Jan 18, 2024
1 parent 405a0f2 commit d5357cc
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 25 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ Ref: https://keepachangelog.com/en/1.0.0/

## Unreleased

## v2.4.0

- [337](https://github.com/ojo-network/price-feeder/pull/337) feat: support fixed gas for vote and prevote transactions.

## Old

### Improvements
- [48](https://github.com/ojo-network/price-feeder/pull/48) Update goreleaser to have release process for umee price-feeder
- [55](https://github.com/ojo-network/price-feeder/pull/55) Update DockerFile to work in umee's e2e test
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,14 @@ Chain rules for checking the free oracle transactions are:
- must be only prevote or vote
- gas is limited to [`MaxMsgGasUsage`](https://github.com/ojo-network/ojo/blob/main/ante/fee.go#L13) constant.

So, if you don't want to pay for gas, TX must be below `MaxMsgGasUsage`. If you set too much gas (which is what is happening when when you set `gas_adjustment` to 2), then the tx will allocate 2x gas, and hence will go above the free quota, so you would need to attach fee to pay for that gas.
So, if you don't want to pay for gas, TX must be below `MaxMsgGasUsage`. If you set too much gas (which is what is happening when you use high `gas_adjustment`, eg more than 2), then the tx will allocate 2x gas, and hence will go above the free quota, so you would need to attach fee to pay for that gas.
The easiest is to just set constant gas. We recommend 10k below the `MaxMsgGasUsage`.

Note that either `gas_adjustment` or `gas` can be used. Both can not be set.
In the PF config file you can set either:

* `gas_adjustment`
* or `gas_prevote` and `gas_vote` - fixed amount of gas used for `MsgAggregateExchangeRatePrevote` and `MsgAggregateExchangeRateVote` transactions respectively.

## Configuration

### `telemetry`
Expand Down
3 changes: 2 additions & 1 deletion cmd/price-feeder.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ func priceFeederCmdHandler(cmd *cobra.Command, args []string) error {
cfg.Account.Validator,
cfg.RPC.GRPCEndpoint,
cfg.GasAdjustment,
cfg.Gas,
cfg.GasPrevote,
cfg.GasVote,
)
if err != nil {
return err
Expand Down
19 changes: 14 additions & 5 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"errors"
"fmt"
"strings"
"time"

"github.com/cosmos/cosmos-sdk/telemetry"
Expand Down Expand Up @@ -47,7 +48,8 @@ type (
RPC RPC `mapstructure:"rpc" validate:"required,gt=0,dive,required"`
Telemetry telemetry.Config `mapstructure:"telemetry"`
GasAdjustment float64 `mapstructure:"gas_adjustment"`
Gas uint64 `mapstructure:"gas"`
GasVote uint64 `mapstructure:"gas_vote"`
GasPrevote uint64 `mapstructure:"gas_prevote"`
ProviderTimeout string `mapstructure:"provider_timeout"`
ProviderMinOverride bool `mapstructure:"provider_min_override"`
ProviderEndpoints []provider.Endpoint `mapstructure:"provider_endpoints" validate:"dive"`
Expand Down Expand Up @@ -169,11 +171,18 @@ func (c Config) validateDeviations() error {
}

func (c Config) validateGas() error {
if c.Gas <= 0 && c.GasAdjustment <= 0 {
return fmt.Errorf("gas or gas adjustment must be set")
var errs []string
if (c.GasPrevote > 0) != (c.GasVote > 0) {
errs = append(errs, "if gas_prevote is set, then gas_vote must be set as well; similarly, if gas_vote is set, then gas_prevote must be set as well")

Check failure on line 176 in config/config.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

line is 150 characters (lll)
}
if c.GasAdjustment > 0 && c.Gas > 0 {
return fmt.Errorf("gas and gas adjustment may not both be set")
if c.GasVote <= 0 && c.GasAdjustment <= 0 {
errs = append(errs, "either gas_vote and gas_prevote must be set or gas_adjustment must be set")
}
if c.GasAdjustment > 0 && c.GasVote > 0 {
errs = append(errs, "gas and gas adjustment may not both be set")
}
if len(errs) > 0 {
return errors.New(strings.Join(errs, ". "))
}
return nil
}
Expand Down
23 changes: 15 additions & 8 deletions oracle/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ type (
Encoding testutil.TestEncodingConfig
GasPrices string
GasAdjustment float64
Gas uint64
GasPrevote uint64
GasVote uint64
GRPCEndpoint string
KeyringPassphrase string
ChainHeight *ChainHeight
Expand All @@ -68,7 +69,8 @@ func NewOracleClient(
validatorAddrString string,
grpcEndpoint string,
gasAdjustment float64,
gas uint64,
gasPrevote uint64,
gasVote uint64,
) (OracleClient, error) {
oracleAddr, err := sdk.AccAddressFromBech32(oracleAddrString)
if err != nil {
Expand All @@ -89,7 +91,8 @@ func NewOracleClient(
ValidatorAddrString: validatorAddrString,
Encoding: umeeapp.MakeEncodingConfig(),
GasAdjustment: gasAdjustment,
Gas: gas,
GasPrevote: gasPrevote,
GasVote: gasVote,
GRPCEndpoint: grpcEndpoint,
}

Expand Down Expand Up @@ -138,7 +141,7 @@ func (r *passReader) Read(p []byte) (n int, err error) {
// BroadcastTx attempts to broadcast a signed transaction. If it fails, a few re-attempts
// will be made until the transaction succeeds or ultimately times out or fails.
// Ref: https://github.com/terra-money/oracle-feeder/blob/baef2a4a02f57a2ffeaa207932b2e03d7fb0fb25/feeder/src/vote.ts#L230
func (oc OracleClient) BroadcastTx(nextBlockHeight, timeoutHeight int64, msgs ...sdk.Msg) error {
func (oc OracleClient) BroadcastTx(nextBlockHeight, timeoutHeight int64, isPrevote bool, msgs sdk.Msg) error {
maxBlockHeight := nextBlockHeight + timeoutHeight
lastCheckHeight := nextBlockHeight - 1

Expand All @@ -147,7 +150,7 @@ func (oc OracleClient) BroadcastTx(nextBlockHeight, timeoutHeight int64, msgs ..
return err
}

factory, err := oc.CreateTxFactory()
factory, err := oc.CreateTxFactory(isPrevote)
if err != nil {
return err
}
Expand All @@ -166,7 +169,7 @@ func (oc OracleClient) BroadcastTx(nextBlockHeight, timeoutHeight int64, msgs ..
// set last check height to latest block height
lastCheckHeight = latestBlockHeight

resp, err := BroadcastTx(clientCtx, factory, msgs...)
resp, err := BroadcastTx(clientCtx, factory, msgs)
if resp != nil && resp.Code != 0 {
telemetry.IncrCounter(1, "failure", "tx", "code")
err = fmt.Errorf("invalid response code from tx: %d", resp.Code)
Expand Down Expand Up @@ -266,7 +269,7 @@ func (oc OracleClient) CreateClientContext() (client.Context, error) {

// CreateTxFactory creates an SDK Factory instance used for transaction
// generation, signing and broadcasting.
func (oc OracleClient) CreateTxFactory() (tx.Factory, error) {
func (oc OracleClient) CreateTxFactory(isPrevote bool) (tx.Factory, error) {
clientCtx, err := oc.CreateClientContext()
if err != nil {
return tx.Factory{}, err
Expand All @@ -283,11 +286,15 @@ func (oc OracleClient) CreateTxFactory() (tx.Factory, error) {
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
WithSimulateAndExecute(true), nil
}
gas := oc.GasVote
if isPrevote {
gas = oc.GasVote
}
return tx.Factory{}.
WithAccountRetriever(clientCtx.AccountRetriever).
WithChainID(oc.ChainID).
WithTxConfig(clientCtx.TxConfig).
WithGas(oc.Gas).
WithGas(gas).
WithGasPrices(oc.GasPrices).
WithKeybase(clientCtx.Keyring).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
Expand Down
15 changes: 8 additions & 7 deletions oracle/oracle.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,24 +557,24 @@ func (o *Oracle) tick(ctx context.Context) error {

exchangeRatesStr := GenerateExchangeRatesString(o.prices)
hash := oracletypes.GetAggregateVoteHash(salt, exchangeRatesStr, valAddr)
preVoteMsg := &oracletypes.MsgAggregateExchangeRatePrevote{
Hash: hash.String(), // hash of prices from the oracle
Feeder: o.oracleClient.OracleAddrString,
Validator: valAddr.String(),
}

isPrevoteOnlyTx := o.previousPrevote == nil

if isPrevoteOnlyTx {
// This timeout could be as small as oracleVotePeriod-indexInVotePeriod,
// but we give it some extra time just in case.
//
// Ref : https://github.com/terra-money/oracle-feeder/blob/baef2a4a02f57a2ffeaa207932b2e03d7fb0fb25/feeder/src/vote.ts#L222
preVoteMsg := &oracletypes.MsgAggregateExchangeRatePrevote{
Hash: hash.String(), // hash of prices from the oracle
Feeder: o.oracleClient.OracleAddrString,
Validator: valAddr.String(),
}
o.logger.Info().
Str("hash", hash.String()).
Str("validator", preVoteMsg.Validator).
Str("feeder", preVoteMsg.Feeder).
Msg("broadcasting pre-vote")
if err := o.oracleClient.BroadcastTx(nextBlockHeight, oracleVotePeriod*2, preVoteMsg); err != nil {
if err := o.oracleClient.BroadcastTx(nextBlockHeight, oracleVotePeriod*2, isPrevoteOnlyTx, preVoteMsg); err != nil {
return err
}

Expand Down Expand Up @@ -606,6 +606,7 @@ func (o *Oracle) tick(ctx context.Context) error {
if err := o.oracleClient.BroadcastTx(
nextBlockHeight,
oracleVotePeriod-indexInVotePeriod,
isPrevoteOnlyTx,
voteMsg,
); err != nil {
return err
Expand Down
7 changes: 5 additions & 2 deletions price-feeder.example.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
config_dir = "umee-provider-config"

gas_adjustment = 1.9
provider_timeout = "1000000s"

gas_prevote = 55000
gas_vote = 160000
# instead of fixed gas settings, gas adjustment can be used:
# gas_adjustment = 1.9

[server]
listen_addr = "0.0.0.0:7171"
read_timeout = "20s"
Expand Down

0 comments on commit d5357cc

Please sign in to comment.