Skip to content

Commit

Permalink
Merge branch 'umee' into feature/update-endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
adamewozniak authored Jan 29, 2024
2 parents 41194dc + 9c240bd commit bd1060c
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 35 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
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ core differences are as follows:
- The `price-feeder` combines both `feeder` and `price-server` into a single
Golang-based application for better UX, testability, and integration.

This instance of the price feeder is intended to be used as a library for [Umee's Price Feeder](https://github.com/umee-network/umee/tree/main/price-feeder), in order to prevent double work.

## Background

The `price-feeder` tool is responsible for performing the following:
Expand Down Expand Up @@ -53,12 +51,25 @@ The keyring's password is defined via environment variables or user input.
More information on the keyring can be found [here](#keyring)
Please see the [example configuration](price-feeder.example.toml) for more details. The path to the node-config is required as the first argument. You can optionally add all configuration options to the node-config file or use the config-dir flag to point to a directory containing the other configuration files.

The files in the provider-config folder define what exchange rates to fetch and what providers to get them from. They also contain deviation thresholds and API endpoints. Please see the [example configuration](ojo-provider-config) for more details.
The files in the provider-config folder define what exchange rates to fetch and what providers to get them from. They also contain deviation thresholds and API endpoints. Please see the [example configuration](umee-provider-config) for more details.

```shell
$ price-feeder /path/to/price_feeder_config.toml
```

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 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`.

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
2 changes: 2 additions & 0 deletions cmd/price-feeder.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ func priceFeederCmdHandler(cmd *cobra.Command, args []string) error {
cfg.Account.Validator,
cfg.RPC.GRPCEndpoint,
cfg.GasAdjustment,
cfg.GasPrevote,
cfg.GasVote,
)
if err != nil {
return err
Expand Down
29 changes: 27 additions & 2 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 @@ -46,7 +47,9 @@ type (
Keyring Keyring `mapstructure:"keyring" validate:"required,gt=0,dive,required"`
RPC RPC `mapstructure:"rpc" validate:"required,gt=0,dive,required"`
Telemetry telemetry.Config `mapstructure:"telemetry"`
GasAdjustment float64 `mapstructure:"gas_adjustment" validate:"required"`
GasAdjustment float64 `mapstructure:"gas_adjustment"`
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 @@ -141,10 +144,12 @@ func (c Config) Validate() (err error) {
if err = c.validateCurrencyPairs(); err != nil {
return err
}

if err = c.validateDeviations(); err != nil {
return err
}
if err = c.validateGas(); err != nil {
return err
}

validate.RegisterStructValidation(telemetryValidation, telemetry.Config{})
validate.RegisterStructValidation(endpointValidation, provider.Endpoint{})
Expand All @@ -165,6 +170,26 @@ func (c Config) validateDeviations() error {
return nil
}

func (c Config) validateGas() error {
var errs []string
if (c.GasPrevote > 0) != (c.GasVote > 0) {
errs = append(errs,
fmt.Sprintf("%s%s", "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"),
)
}
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
}

func (c Config) validateCurrencyPairs() error {
OUTER:
for _, cp := range c.CurrencyPairs {
Expand Down
12 changes: 7 additions & 5 deletions config/supported_assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ var (
{Base: "ATOM", Quote: "USD"}: {},
{Base: "OSMO", Quote: "USD"}: {},

{Base: "OSMO", Quote: "USDT"}: {},
{Base: "JUNO", Quote: "USDT"}: {},
{Base: "UMEE", Quote: "USDT"}: {},
{Base: "WETH", Quote: "USDC"}: {},
{Base: "WBTC", Quote: "WETH"}: {},
{Base: "OSMO", Quote: "USDT"}: {},
{Base: "JUNO", Quote: "USDT"}: {},
{Base: "UMEE", Quote: "USDT"}: {},
{Base: "WETH", Quote: "USDC"}: {},
{Base: "WBTC", Quote: "WETH"}: {},
{Base: "STARS", Quote: "OSMO"}: {},
{Base: "TIA", Quote: "USDT"}: {},
}

SupportedUniswapCurrencies = map[string]struct{}{
Expand Down
37 changes: 28 additions & 9 deletions oracle/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ type (
Encoding testutil.TestEncodingConfig
GasPrices string
GasAdjustment float64
GasPrevote uint64
GasVote uint64
GRPCEndpoint string
KeyringPassphrase string
ChainHeight *ChainHeight
Expand All @@ -67,6 +69,8 @@ func NewOracleClient(
validatorAddrString string,
grpcEndpoint string,
gasAdjustment float64,
gasPrevote uint64,
gasVote uint64,
) (OracleClient, error) {
oracleAddr, err := sdk.AccAddressFromBech32(oracleAddrString)
if err != nil {
Expand All @@ -87,6 +91,8 @@ func NewOracleClient(
ValidatorAddrString: validatorAddrString,
Encoding: umeeapp.MakeEncodingConfig(),
GasAdjustment: gasAdjustment,
GasPrevote: gasPrevote,
GasVote: gasVote,
GRPCEndpoint: grpcEndpoint,
}

Expand Down Expand Up @@ -135,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 @@ -144,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 @@ -163,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 @@ -263,21 +269,34 @@ 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
}

txFactory := tx.Factory{}.
if oc.GasAdjustment > 0 {
return tx.Factory{}.
WithAccountRetriever(clientCtx.AccountRetriever).
WithChainID(oc.ChainID).
WithTxConfig(clientCtx.TxConfig).
WithGasAdjustment(oc.GasAdjustment).
WithGasPrices(oc.GasPrices).
WithKeybase(clientCtx.Keyring).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
WithSimulateAndExecute(true), nil
}
gas := oc.GasVote
if isPrevote {
gas = oc.GasPrevote
}
return tx.Factory{}.
WithAccountRetriever(clientCtx.AccountRetriever).
WithChainID(oc.ChainID).
WithTxConfig(clientCtx.TxConfig).
WithGasAdjustment(oc.GasAdjustment).
WithGas(gas).
WithGasPrices(oc.GasPrices).
WithKeybase(clientCtx.Keyring).
WithSignMode(signing.SignMode_SIGN_MODE_DIRECT).
WithSimulateAndExecute(true)

return txFactory, nil
WithSimulateAndExecute(true), nil
}
12 changes: 7 additions & 5 deletions oracle/client/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ func BroadcastTx(clientCtx client.Context, txf tx.Factory, msgs ...sdk.Msg) (*sd
return nil, err
}

_, adjusted, err := tx.CalculateGas(clientCtx, txf, msgs...)
if err != nil {
return nil, err
}
if txf.GasAdjustment() > 0 {
_, adjusted, err := tx.CalculateGas(clientCtx, txf, msgs...)
if err != nil {
return nil, err
}

txf = txf.WithGas(adjusted)
txf = txf.WithGas(adjusted)
}

unsignedTx, err := txf.BuildUnsignedTx(msgs...)
if err != nil {
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.1
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
17 changes: 16 additions & 1 deletion umee-provider-config/currency-pairs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,19 @@ providers = [
"bitget",
"gate",
]
quote = "USDT"
quote = "USDT"

[[currency_pairs]]
base = "STRD"
providers = [
"osmosis",
]
quote = "OSMO"

[[currency_pairs]]
base = "STRD"
providers = [
"osmosis",
]
quote = "USDC"

6 changes: 5 additions & 1 deletion umee-provider-config/deviation-thresholds.toml
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,8 @@ threshold = "2"

[[deviation_thresholds]]
base = "TIA"
threshold = "2"
threshold = "2"

[[deviation_thresholds]]
base = "STRD"
threshold = "2"

0 comments on commit bd1060c

Please sign in to comment.