From 6c75a764732a0b07be2c754fc2002637a43ec6a4 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Mon, 4 Mar 2024 15:19:35 -0500 Subject: [PATCH 01/27] feat: Oracle vote extension handler --- abci/preblock.go | 69 ++++++++++ abci/proposal.go | 173 ++++++++++++++++++++++++++ abci/util.go | 23 ++++ abci/voteextension.go | 152 ++++++++++++++++++++++ app/app.go | 29 +++++ buf.work.yaml | 3 + cmd/ojod/cmd/commands.go | 3 +- config.yml | 4 + go.mod | 29 ++++- go.sum | 57 +++++++-- pricefeeder/price-feeder.example.toml | 4 +- pricefeeder/pricefeeder.go | 12 +- proto/buf.gen.pulsar.yaml | 22 ++++ proto/buf.gen.sta.yaml | 15 +++ proto/buf.gen.swagger.yaml | 14 +++ proto/buf.gen.ts.yaml | 18 +++ scripts/single-node.sh | 12 +- tools/tools.go | 10 +- x/oracle/abci.go | 2 + x/oracle/keeper/keeper.go | 3 + 20 files changed, 625 insertions(+), 29 deletions(-) create mode 100644 abci/preblock.go create mode 100644 abci/proposal.go create mode 100644 abci/util.go create mode 100644 abci/voteextension.go create mode 100644 buf.work.yaml create mode 100644 proto/buf.gen.pulsar.yaml create mode 100644 proto/buf.gen.sta.yaml create mode 100644 proto/buf.gen.swagger.yaml create mode 100644 proto/buf.gen.ts.yaml diff --git a/abci/preblock.go b/abci/preblock.go new file mode 100644 index 00000000..7bd61da1 --- /dev/null +++ b/abci/preblock.go @@ -0,0 +1,69 @@ +package abci + +import ( + "encoding/json" + "fmt" + + "cosmossdk.io/log" + cometabci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/ojo-network/ojo/x/oracle/keeper" +) + +type PreBlockHandler struct { + logger log.Logger + keeper keeper.Keeper +} + +func NewPreBlockHandler(logger log.Logger, keeper keeper.Keeper) *PreBlockHandler { + return &PreBlockHandler{ + logger: logger, + keeper: keeper, + } +} + +func (h *PreBlockHandler) PreBlocker() sdk.PreBlocker { + return func(ctx sdk.Context, req *cometabci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) { + if req == nil { + err := fmt.Errorf("preblocker received a nil request") + h.logger.Error(err.Error()) + return nil, err + } + + res := &sdk.ResponsePreBlock{} + if len(req.Txs) == 0 { + return res, nil + } + + voteExtensionsEnabled := VoteExtensionsEnabled(ctx) + if voteExtensionsEnabled { + var injectedVoteExtTx AggregateExchangeRateVotes + if err := json.Unmarshal(req.Txs[0], &injectedVoteExtTx); err != nil { + h.logger.Error("failed to decode injected vote extension tx", "err", err) + return nil, err + } + h.logger.Info("PreBlocker injectedVoteExtTx", "tx", injectedVoteExtTx) + // set oracle exchange rate votes using the passed in context, which will make + // these votes available in the current block. + for _, exchangeRateVote := range injectedVoteExtTx.ExchangeRateVotes { + valAddr, err := sdk.ValAddressFromBech32(exchangeRateVote.Voter) + if err != nil { + return nil, err + } + h.logger.Info( + "setting oracle exchange rate vote", + "exchange rate vote", exchangeRateVote, + ) + h.keeper.SetAggregateExchangeRateVote(ctx, valAddr, exchangeRateVote) + } + } + + h.logger.Info( + "oracle preblocker executed", + "vote_extensions_enabled", voteExtensionsEnabled, + ) + + return res, nil + } +} diff --git a/abci/proposal.go b/abci/proposal.go new file mode 100644 index 00000000..24248407 --- /dev/null +++ b/abci/proposal.go @@ -0,0 +1,173 @@ +package abci + +import ( + "encoding/json" + "errors" + "fmt" + + "cosmossdk.io/log" + cometabci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/ojo-network/ojo/x/oracle/keeper" + oracletypes "github.com/ojo-network/ojo/x/oracle/types" +) + +type AggregateExchangeRateVotes struct { + ExchangeRateVotes []oracletypes.AggregateExchangeRateVote + ExtendedCommitInfo cometabci.ExtendedCommitInfo +} + +type ProposalHandler struct { + logger log.Logger + keeper keeper.Keeper + valStore baseapp.ValidatorStore +} + +func NewProposalHandler(logger log.Logger, keeper keeper.Keeper, valStore baseapp.ValidatorStore) *ProposalHandler { + return &ProposalHandler{ + logger: logger, + keeper: keeper, + valStore: valStore, + } +} + +func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler { + return func(ctx sdk.Context, req *cometabci.RequestPrepareProposal) (*cometabci.ResponsePrepareProposal, error) { + if req == nil { + err := fmt.Errorf("prepare proposal received a nil request") + h.logger.Error(err.Error()) + return nil, err + } + + err := baseapp.ValidateVoteExtensions(ctx, h.valStore, req.Height, ctx.ChainID(), req.LocalLastCommit) + if err != nil { + return nil, err + } + + if req.Txs == nil { + err := fmt.Errorf("prepare proposal received a request with nil Txs") + h.logger.Error( + "height", req.Height, + err.Error(), + ) + return nil, err + } + + proposalTxs := req.Txs + h.logger.Info("proposalTxs before", "txs", proposalTxs) + + voteExtensionsEnabled := VoteExtensionsEnabled(ctx) + if voteExtensionsEnabled { + exchangeRateVotes, err := h.generateExchangeRateVotes(ctx, req.LocalLastCommit) + if err != nil { + return nil, errors.New("failed to generate exchange rate votes") + } + + injectedVoteExtTx := AggregateExchangeRateVotes{ + ExchangeRateVotes: exchangeRateVotes, + ExtendedCommitInfo: req.LocalLastCommit, + } + + // TODO: Switch from stdlib JSON encoding to a more performant mechanism. + bz, err := json.Marshal(injectedVoteExtTx) + if err != nil { + h.logger.Error("failed to encode injected vote extension tx", "err", err) + return nil, errors.New("failed to encode injected vote extension tx") + } + + // Inject a "fake" tx into the proposal s.t. validators can decode, verify, + // and store the oracle exchange rate votes. + proposalTxs = append([][]byte{bz}, proposalTxs...) + } + + h.logger.Info("proposalTxs after", "txs", proposalTxs) + + h.logger.Info( + "prepared proposal", + "txs", len(proposalTxs), + "vote_extensions_enabled", voteExtensionsEnabled, + ) + + return &cometabci.ResponsePrepareProposal{ + Txs: proposalTxs, + }, nil + } +} + +func (h *ProposalHandler) ProcessProposal() sdk.ProcessProposalHandler { + return func(ctx sdk.Context, req *cometabci.RequestProcessProposal) (*cometabci.ResponseProcessProposal, error) { + if req == nil { + err := fmt.Errorf("process proposal received a nil request") + h.logger.Error(err.Error()) + return nil, err + } + + if req.Txs == nil { + err := fmt.Errorf("process proposal received a request with nil Txs") + h.logger.Error( + "height", req.Height, + err.Error(), + ) + return nil, err + } + + voteExtensionsEnabled := VoteExtensionsEnabled(ctx) + if voteExtensionsEnabled { + var injectedVoteExtTx AggregateExchangeRateVotes + if err := json.Unmarshal(req.Txs[0], &injectedVoteExtTx); err != nil { + h.logger.Error("failed to decode injected vote extension tx", "err", err) + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, nil + } + h.logger.Info("ProcessProposal injectedVoteExtTx", "tx", injectedVoteExtTx) + err := baseapp.ValidateVoteExtensions( + ctx, + h.valStore, + req.Height, + ctx.ChainID(), + injectedVoteExtTx.ExtendedCommitInfo, + ) + if err != nil { + return nil, err + } + + // Verify the proposer's oracle exchange rate votes by computing the same + // calculation and comparing the results. + } + + h.logger.Info( + "processed proposal", + "txs", len(req.Txs), + "vote_extensions_enabled", voteExtensionsEnabled, + ) + + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_ACCEPT}, nil + } +} + +func (h *ProposalHandler) generateExchangeRateVotes( + ctx sdk.Context, + ci cometabci.ExtendedCommitInfo, +) (votes []oracletypes.AggregateExchangeRateVote, err error) { + for _, vote := range ci.Votes { + if vote.BlockIdFlag != cmtproto.BlockIDFlagCommit { + continue + } + + var voteExt OracleVoteExtension + if err := json.Unmarshal(vote.VoteExtension, &voteExt); err != nil { + h.logger.Error( + "failed to decode vote extension", + "err", err, + "validator", fmt.Sprintf("%x", vote.Validator.Address), + ) + return nil, err + } + exchangeRateVote := oracletypes.NewAggregateExchangeRateVote(voteExt.ExchangeRates, vote.Validator.Address) + votes = append(votes, exchangeRateVote) + } + + return votes, nil +} diff --git a/abci/util.go b/abci/util.go new file mode 100644 index 00000000..18758237 --- /dev/null +++ b/abci/util.go @@ -0,0 +1,23 @@ +package abci + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// VoteExtensionsEnabled determines if vote extensions are enabled for the current block. +func VoteExtensionsEnabled(ctx sdk.Context) bool { + cp := ctx.ConsensusParams() + if cp.Abci == nil || cp.Abci.VoteExtensionsEnableHeight == 0 { + return false + } + + // Per the cosmos sdk, the first block should not utilize the latest finalize block state. This means + // vote extensions should NOT be making state changes. + // + // Ref: https://github.com/cosmos/cosmos-sdk/blob/2100a73dcea634ce914977dbddb4991a020ee345/baseapp/baseapp.go#L488-L495 + if ctx.BlockHeight() <= 1 { + return false + } + + return cp.Abci.VoteExtensionsEnableHeight < ctx.BlockHeight() +} diff --git a/abci/voteextension.go b/abci/voteextension.go new file mode 100644 index 00000000..540898b9 --- /dev/null +++ b/abci/voteextension.go @@ -0,0 +1,152 @@ +package abci + +import ( + "encoding/json" + "fmt" + + "cosmossdk.io/log" + cometabci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/ojo-network/ojo/pricefeeder" + "github.com/ojo-network/ojo/x/oracle/keeper" + "github.com/ojo-network/ojo/x/oracle/types" + "github.com/ojo-network/price-feeder/oracle" +) + +// OracleVoteExtension defines the canonical vote extension structure. +type OracleVoteExtension struct { + Height int64 + ExchangeRates sdk.DecCoins +} + +type VoteExtHandler struct { + logger log.Logger + oracleKeeper keeper.Keeper + priceFeeder *pricefeeder.PriceFeeder +} + +// NewVoteExtensionHandler returns a new VoteExtensionHandler. +func NewVoteExtensionHandler( + logger log.Logger, + oracleKeeper keeper.Keeper, + priceFeeder *pricefeeder.PriceFeeder, +) *VoteExtHandler { + return &VoteExtHandler{ + logger: logger, + oracleKeeper: oracleKeeper, + priceFeeder: priceFeeder, + } +} + +func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { + return func(ctx sdk.Context, req *cometabci.RequestExtendVote) (resp *cometabci.ResponseExtendVote, err error) { + defer func() { + // catch panics if possible + if r := recover(); r != nil { + h.logger.Error( + "recovered from panic in ExtendVoteHandler", + "err", r, + ) + + resp, err = &cometabci.ResponseExtendVote{VoteExtension: []byte{}}, fmt.Errorf("recovered application panic in ExtendVote: %v", r) + } + }() + + if req == nil { + err := fmt.Errorf("extend vote handler received a nil request") + h.logger.Error(err.Error()) + return nil, err + } + + // Get prices from Oracle Keeper's pricefeeder and generate vote msg + if h.priceFeeder.Oracle == nil { + err := fmt.Errorf("Price Feeder Oracle not set") + h.logger.Error(err.Error()) + return nil, err + } + prices := h.priceFeeder.Oracle.GetPrices() + h.logger.Info("Price feeder prices", "prices", prices) + exchangeRatesStr := oracle.GenerateExchangeRatesString(prices) + + // Parse as DecCoins + exchangeRates, err := types.ParseExchangeRateDecCoins(exchangeRatesStr) + if err != nil { + err := fmt.Errorf("extend vote handler received invalid exchange rate %w", types.ErrInvalidExchangeRate) + h.logger.Error( + "height", req.Height, + err.Error(), + ) + return nil, err + } + + // Filter out rates which aren't included in the AcceptList + acceptList := h.oracleKeeper.AcceptList(ctx) + filteredDecCoins := sdk.DecCoins{} + for _, decCoin := range exchangeRates { + if acceptList.Contains(decCoin.Denom) { + filteredDecCoins = append(filteredDecCoins, decCoin) + } + } + + voteExt := OracleVoteExtension{ + Height: req.Height, + ExchangeRates: filteredDecCoins, + } + + bz, err := json.Marshal(voteExt) + if err != nil { + err := fmt.Errorf("failed to marshal vote extension: %w", err) + h.logger.Error( + "height", req.Height, + err.Error(), + ) + return nil, err + } + h.logger.Info( + "created vote extension", + "height", req.Height, + ) + + return &cometabci.ResponseExtendVote{VoteExtension: bz}, nil + } +} + +func (h *VoteExtHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { + return func(ctx sdk.Context, req *cometabci.RequestVerifyVoteExtension) (*cometabci.ResponseVerifyVoteExtension, error) { + if req == nil { + err := fmt.Errorf("verify vote extension handler received a nil request") + h.logger.Error(err.Error()) + return nil, err + } + + var voteExt OracleVoteExtension + err := json.Unmarshal(req.VoteExtension, &voteExt) + if err != nil { + err := fmt.Errorf("verify vote extension handler failed to unmarshal vote extension: %w", err) + h.logger.Error( + "height", req.Height, + err.Error(), + ) + return &cometabci.ResponseVerifyVoteExtension{Status: cometabci.ResponseVerifyVoteExtension_REJECT}, err + } + + if voteExt.Height != req.Height { + err := fmt.Errorf( + "verify vote extension handler received vote extension height that doesn't"+ + "match request height; expected: %d, got: %d", + req.Height, + voteExt.Height, + ) + h.logger.Error(err.Error()) + return &cometabci.ResponseVerifyVoteExtension{Status: cometabci.ResponseVerifyVoteExtension_REJECT}, err + } + + h.logger.Info( + "verfied vote extension", + "height", req.Height, + ) + + return &cometabci.ResponseVerifyVoteExtension{Status: cometabci.ResponseVerifyVoteExtension_ACCEPT}, nil + } +} diff --git a/app/app.go b/app/app.go index 4dd1c63f..efac9f92 100644 --- a/app/app.go +++ b/app/app.go @@ -119,6 +119,9 @@ import ( airdropkeeper "github.com/ojo-network/ojo/x/airdrop/keeper" airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" + ojoabci "github.com/ojo-network/ojo/abci" + "github.com/ojo-network/ojo/pricefeeder" + customante "github.com/ojo-network/ojo/ante" ) @@ -216,6 +219,8 @@ type App struct { // module configurator configurator module.Configurator + + PriceFeeder *pricefeeder.PriceFeeder } // New returns a reference to an initialized blockchain app @@ -723,6 +728,30 @@ func New( app.StateSimulationManager = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules) app.StateSimulationManager.RegisterStoreDecoders() + proposalHandler := ojoabci.NewProposalHandler( + app.Logger(), + app.OracleKeeper, + app.StakingKeeper, + ) + app.SetPrepareProposal(proposalHandler.PrepareProposal()) + app.SetProcessProposal(proposalHandler.ProcessProposal()) + + preBlockHandler := ojoabci.NewPreBlockHandler( + app.Logger(), + app.OracleKeeper, + ) + app.SetPreBlocker(preBlockHandler.PreBlocker()) + + // initialize empty price feeder object to pass reference into vote extension handler + app.PriceFeeder = &pricefeeder.PriceFeeder{} + voteExtensionsHandler := ojoabci.NewVoteExtensionHandler( + app.Logger(), + app.OracleKeeper, + app.PriceFeeder, + ) + app.SetExtendVoteHandler(voteExtensionsHandler.ExtendVoteHandler()) + app.SetVerifyVoteExtensionHandler(voteExtensionsHandler.VerifyVoteExtensionHandler()) + // initialize stores app.MountKVStores(keys) app.MountTransientStores(tkeys) diff --git a/buf.work.yaml b/buf.work.yaml new file mode 100644 index 00000000..1878b341 --- /dev/null +++ b/buf.work.yaml @@ -0,0 +1,3 @@ +version: v1 +directories: + - proto diff --git a/cmd/ojod/cmd/commands.go b/cmd/ojod/cmd/commands.go index 0aca72a1..77fd4c0f 100644 --- a/cmd/ojod/cmd/commands.go +++ b/cmd/ojod/cmd/commands.go @@ -30,7 +30,6 @@ import ( "github.com/spf13/cobra" app "github.com/ojo-network/ojo/app" - "github.com/ojo-network/ojo/pricefeeder" oracletypes "github.com/ojo-network/ojo/x/oracle/types" ) @@ -208,7 +207,7 @@ func newApp( var oracleGenState oracletypes.GenesisState app.AppCodec().MustUnmarshalJSON(app.DefaultGenesis()[oracletypes.ModuleName], &oracleGenState) go func() { - err := pricefeeder.Start(oracleGenState.Params) + err := app.PriceFeeder.Start(oracleGenState.Params) if err != nil { panic(err) } diff --git a/config.yml b/config.yml index 9ad1d70b..1f95cfe7 100644 --- a/config.yml +++ b/config.yml @@ -33,6 +33,10 @@ genesis: staking: params: bond_denom: uojo + consensus: + params: + abci: + vote_extensions_enable_height: "2" chain_id: ojo-testnet validators: - name: alice diff --git a/go.mod b/go.mod index 89ad0aab..a968497c 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( cosmossdk.io/x/tx v0.12.0 cosmossdk.io/x/upgrade v0.1.0 github.com/armon/go-metrics v0.4.1 + github.com/bufbuild/buf v1.15.1 github.com/cometbft/cometbft v0.38.5 github.com/cosmos/cosmos-db v1.0.0 github.com/cosmos/cosmos-proto v1.0.0-beta.3 @@ -32,6 +33,7 @@ require ( github.com/golangci/golangci-lint v1.55.2 github.com/gorilla/mux v1.8.1 github.com/grpc-ecosystem/grpc-gateway v1.16.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 github.com/mgechev/revive v1.3.6 github.com/mitchellh/mapstructure v1.5.0 github.com/ojo-network/price-feeder v0.1.10-0.20240221234245-b3d7d675adc9 @@ -43,7 +45,7 @@ require ( github.com/stretchr/testify v1.8.4 golang.org/x/sync v0.5.0 golang.org/x/tools v0.16.1 - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 + google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe google.golang.org/grpc v1.61.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 google.golang.org/protobuf v1.32.0 @@ -97,6 +99,8 @@ require ( github.com/breml/errchkjson v0.3.6 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 // indirect + github.com/bufbuild/connect-go v1.5.2 // indirect + github.com/bufbuild/protocompile v0.6.0 // indirect github.com/butuzov/ireturn v0.2.2 // indirect github.com/butuzov/mirror v1.1.0 // indirect github.com/catenacyber/perfsprint v0.2.0 // indirect @@ -120,6 +124,7 @@ require ( github.com/cosmos/iavl v1.0.0 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/creachadair/atomicfile v0.3.1 // indirect github.com/creachadair/tomledit v0.0.24 // indirect github.com/curioswitch/go-reassign v0.2.0 // indirect @@ -133,7 +138,9 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/docker/cli v24.0.2+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v24.0.2+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -143,13 +150,16 @@ require ( github.com/ettle/strcase v0.1.1 // indirect github.com/fatih/color v1.16.0 // indirect github.com/fatih/structtag v1.2.0 // indirect + github.com/felixge/fgprof v0.9.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/firefart/nonamedreturns v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fzipp/gocyclo v0.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/ghostiam/protogetter v0.2.3 // indirect + github.com/go-chi/chi/v5 v5.0.8 // indirect github.com/go-critic/go-critic v0.9.0 // indirect github.com/go-kit/kit v0.13.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -170,6 +180,7 @@ require ( github.com/gobwas/glob v0.2.3 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect + github.com/gofrs/uuid/v5 v5.0.0 // indirect github.com/gogo/googleapis v1.4.1 // indirect github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -186,7 +197,9 @@ require ( github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-containerregistry v0.13.0 // indirect github.com/google/orderedcode v0.0.1 // indirect + github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.4.0 // indirect @@ -222,6 +235,7 @@ require ( github.com/imdario/mergo v0.3.16 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 // indirect github.com/jgautheron/goconst v1.6.0 // indirect github.com/jingyugao/rowserrcheck v1.1.1 // indirect github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect @@ -233,6 +247,7 @@ require ( github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kulti/thelper v0.6.3 // indirect @@ -263,6 +278,7 @@ require ( github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/moby/term v0.5.0 // indirect github.com/moricho/tparallel v0.3.1 // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/nakabonne/nestif v0.3.1 // indirect github.com/nishanths/exhaustive v0.11.0 // indirect @@ -277,7 +293,9 @@ require ( github.com/opencontainers/runc v1.1.7 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polyfloyd/go-errorlint v1.4.5 // indirect github.com/prometheus/client_golang v1.18.0 // indirect @@ -293,6 +311,7 @@ require ( github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/cors v1.10.1 // indirect github.com/rs/xid v1.5.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/ryancurrah/gomodguard v1.3.0 // indirect github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect @@ -345,8 +364,10 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.19.0 // indirect go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect go.opentelemetry.io/otel/trace v1.19.0 // indirect go.tmz.dev/musttag v0.7.2 // indirect + go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.25.0 // indirect golang.org/x/crypto v0.18.0 // indirect @@ -354,15 +375,15 @@ require ( golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/net v0.20.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/oauth2 v0.16.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/term v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/api v0.153.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect honnef.co/go/tools v0.4.6 // indirect diff --git a/go.sum b/go.sum index bf870ad4..f65a6d8e 100644 --- a/go.sum +++ b/go.sum @@ -333,6 +333,10 @@ github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipus github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/bufbuild/buf v1.15.1 h1:v7sK2uMEsGX4Z2hvu+xiMheH3C3AKBGfxPBgdUZYDQ8= +github.com/bufbuild/buf v1.15.1/go.mod h1:TQeGKam1QMfHy/xsSnnMpxN3JK5HBb6aNvZj4m52gkE= +github.com/bufbuild/connect-go v1.5.2 h1:G4EZd5gF1U1ZhhbVJXplbuUnfKpBZ5j5izqIwu2g2W8= +github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/butuzov/ireturn v0.2.2 h1:jWI36dxXwVrI+RnXDwux2IZOewpmfv930OuIRfaBUJ0= @@ -405,6 +409,8 @@ github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AK github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0= github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU= github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= +github.com/containerd/stargz-snapshotter/estargz v0.12.1 h1:+7nYmHJb0tEkcRaAW+MHqoKaJYZmkikupxCqVtmPuY0= +github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -438,6 +444,7 @@ github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5n github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creachadair/atomicfile v0.3.1 h1:yQORkHjSYySh/tv5th1dkKcn02NEW5JleB84sjt+W4Q= github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= @@ -476,8 +483,12 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM= github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg= github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -517,6 +528,8 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/firefart/nonamedreturns v1.0.4 h1:abzI1p7mAEPYuR4A+VLKn4eNDOycjYo2phmY9sfv40Y= @@ -537,6 +550,7 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI= github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghostiam/protogetter v0.2.3 h1:qdv2pzo3BpLqezwqfGDLZ+nHEYmc5bUpIdsMbBVwMjw= github.com/ghostiam/protogetter v0.2.3/go.mod h1:KmNLOsy1v04hKbvZs8EfGI1fk39AgTdRDxWNYPfXVc4= @@ -545,6 +559,8 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-critic/go-critic v0.9.0 h1:Pmys9qvU3pSML/3GEQ2Xd9RZ/ip+aXHKILuxczKGV/U= github.com/go-critic/go-critic v0.9.0/go.mod h1:5P8tdXL7m/6qnyG6oRAlYLORvoXH0WDypYgAEmagT40= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -625,6 +641,8 @@ github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= +github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= @@ -714,6 +732,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-containerregistry v0.13.0 h1:y1C7Z3e149OJbOPDBxLYR8ITPz8dTKqQwjErKVHJC8k= +github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -741,6 +761,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso= github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -804,6 +825,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= @@ -873,6 +896,7 @@ github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSAS github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= @@ -881,6 +905,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84 h1:2uT3aivO7NVpUPGcQX7RbHijHMyWix/yCnIrCWc+5co= +github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= github.com/jgautheron/goconst v1.6.0 h1:gbMLWKRMkzAc6kYsQL6/TxaoBUg3Jm9LSF/Ih1ADWGA= github.com/jgautheron/goconst v1.6.0/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= @@ -928,6 +954,8 @@ github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -1033,6 +1061,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moricho/tparallel v0.3.1 h1:fQKD4U1wRMAYNngDonW5XupoB/ZGJHdpzrWqgyg9krA= github.com/moricho/tparallel v0.3.1/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -1124,12 +1154,16 @@ github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0 github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1205,6 +1239,7 @@ github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryancurrah/gomodguard v1.3.0 h1:q15RT/pd6UggBXVBuLps8BXRvl5GPBcwVA7BJHMLuTw= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= @@ -1345,6 +1380,8 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/uudashr/gocognit v1.1.2 h1:l6BAEKJqQH2UpKAPKdMfZf5kE4W/2xk8pfU1OVLvniI= github.com/uudashr/gocognit v1.1.2/go.mod h1:aAVdLURqcanke8h3vg35BC++eseDm66Z7KmchI5et4k= +github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1409,6 +1446,8 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= @@ -1578,8 +1617,8 @@ golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= -golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= -golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1665,6 +1704,7 @@ golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1673,6 +1713,7 @@ golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1993,12 +2034,12 @@ google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqw google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= -google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= diff --git a/pricefeeder/price-feeder.example.toml b/pricefeeder/price-feeder.example.toml index 9e3e6d52..882dded8 100644 --- a/pricefeeder/price-feeder.example.toml +++ b/pricefeeder/price-feeder.example.toml @@ -319,7 +319,6 @@ read_timeout = "20s" verbose_cors = true write_timeout = "20s" - [rpc] grpc_endpoint = "localhost:9090" rpc_timeout = "100ms" @@ -330,7 +329,6 @@ enable-hostname = true enable-hostname-label = true enable-service-label = true enabled = true -global-labels = [["chain_id", "ojo-devnet-01"]] +global-labels = [["chain_id", "ojo-testnet"]] service-name = "price-feeder" prometheus-retention-time = 100 - diff --git a/pricefeeder/pricefeeder.go b/pricefeeder/pricefeeder.go index c7387944..3e059241 100644 --- a/pricefeeder/pricefeeder.go +++ b/pricefeeder/pricefeeder.go @@ -34,7 +34,11 @@ const ( envOracleTickTime = "PRICE_FEEDER_ORACLE_TICK_TIME" ) -func Start(oracleParams types.Params) error { +type PriceFeeder struct { + Oracle *oracle.Oracle +} + +func (pf *PriceFeeder) Start(oracleParams types.Params) error { logWriter := zerolog.ConsoleWriter{Out: os.Stderr} logLevel, err := zerolog.ParseLevel(os.Getenv(envDebugLevel)) if err != nil { @@ -78,7 +82,7 @@ func Start(oracleParams types.Params) error { } } - oracle := oracle.New( + pf.Oracle = oracle.New( logger, client.OracleClient{}, providers, @@ -105,11 +109,11 @@ func Start(oracleParams types.Params) error { g.Go(func() error { // start the process that observes and publishes exchange prices - return startPriceFeeder(ctx, logger, cfg, oracle, metrics) + return startPriceFeeder(ctx, logger, cfg, pf.Oracle, metrics) }) g.Go(func() error { // start the process that calculates oracle prices - return startPriceOracle(ctx, logger, oracle, oracleParams, oracleTickTime) + return startPriceOracle(ctx, logger, pf.Oracle, oracleParams, oracleTickTime) }) // Block main process until all spawned goroutines have gracefully exited and diff --git a/proto/buf.gen.pulsar.yaml b/proto/buf.gen.pulsar.yaml new file mode 100644 index 00000000..e8fffdb2 --- /dev/null +++ b/proto/buf.gen.pulsar.yaml @@ -0,0 +1,22 @@ +# This file is auto-generated from Ignite. You can edit +# the file content but do not change the file name or path. +# +# buf.gen.pulsar.yaml +# +version: v1 +managed: + enabled: true + go_package_prefix: + default: cosmossdk.io/api + except: + - buf.build/googleapis/googleapis + - buf.build/cosmos/gogo-proto + - buf.build/cosmos/cosmos-proto + override: +plugins: + - name: go-pulsar + out: ./api + opt: paths=source_relative + - name: go-grpc + out: ./api + opt: paths=source_relative diff --git a/proto/buf.gen.sta.yaml b/proto/buf.gen.sta.yaml new file mode 100644 index 00000000..4444f5e7 --- /dev/null +++ b/proto/buf.gen.sta.yaml @@ -0,0 +1,15 @@ +# This file is auto-generated from Ignite. You can edit +# the file content but do not change the file name or path. +# +# buf.gen.sta.yaml +# +version: v1 +plugins: + - name: openapiv2 + out: . + opt: + - logtostderr=true + - openapi_naming_strategy=simple + - ignore_comments=true + - simple_operation_ids=false + - json_names_for_fields=false diff --git a/proto/buf.gen.swagger.yaml b/proto/buf.gen.swagger.yaml new file mode 100644 index 00000000..58d30d86 --- /dev/null +++ b/proto/buf.gen.swagger.yaml @@ -0,0 +1,14 @@ +# This file is auto-generated from Ignite. You can edit +# the file content but do not change the file name or path. +# +# buf.gen.swagger.yaml +# +version: v1 +plugins: + - name: openapiv2 + out: . + opt: + - logtostderr=true + - openapi_naming_strategy=fqn + - json_names_for_fields=false + - generate_unbound_methods=true \ No newline at end of file diff --git a/proto/buf.gen.ts.yaml b/proto/buf.gen.ts.yaml new file mode 100644 index 00000000..c484fb3a --- /dev/null +++ b/proto/buf.gen.ts.yaml @@ -0,0 +1,18 @@ +# This file is auto-generated from Ignite. You can edit +# the file content but do not change the file name or path. +# +# buf.gen.ts.yaml +# +version: v1 +managed: + enabled: true +plugins: + - plugin: buf.build/community/stephenh-ts-proto + out: . + opt: + - logtostderr=true + - allow_merge=true + - json_names_for_fields=false + - ts_proto_opt=snakeToCamel=true + - ts_proto_opt=esModuleInterop=true + - ts_proto_out=. diff --git a/scripts/single-node.sh b/scripts/single-node.sh index 0b2edcc3..99a04067 100755 --- a/scripts/single-node.sh +++ b/scripts/single-node.sh @@ -15,7 +15,7 @@ CWD="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" PRICE_FEEDER_CONFIG_PATH="${CWD}/../pricefeeder/price-feeder.example.toml" export PRICE_FEEDER_CONFIG=$(realpath "$PRICE_FEEDER_CONFIG_PATH") -export PRICE_FEEDER_CHAIN_CONFIG="TRUE" +export PRICE_FEEDER_CHAIN_CONFIG="FALSE" export PRICE_FEEDER_LOG_LEVEL="DEBUG" export PRICE_FEEDER_ORACLE_TICK_TIME="5s" @@ -125,7 +125,7 @@ if [[ ! -d "$hdir" ]]; then echo "--- Patching genesis..." if [[ "$STAKE_DENOM" == "$DENOM" ]]; then - jq '.consensus_params["block"]["time_iota_ms"]="5000" + jq '.consensus["params"]["abci"]["vote_extensions_enable_height"]="2" | .app_state["crisis"]["constant_fee"]["denom"]="'$DENOM'" | .app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="'$DENOM'" | .app_state["mint"]["params"]["mint_denom"]="'$DENOM'" @@ -142,6 +142,12 @@ if [[ ! -d "$hdir" ]]; then $NODE_BIN $home0 collect-gentxs > /dev/null + # copy centralized sequencer address into genesis.json + # Note: validator and sequencer are used interchangeably here + ADDRESS=$(jq -r '.address' $n0cfgDir/priv_validator_key.json) + PUB_KEY=$(jq -r '.pub_key' $n0cfgDir/priv_validator_key.json) + jq --argjson pubKey "$PUB_KEY" '.consensus["validators"]=[{"address": "'$ADDRESS'", "pub_key": $pubKey, "power": "1000000000000", "name": "Rollkit Sequencer"}]' $n0cfgDir/genesis.json > $n0cfgDir/tmp_genesis.json && mv $n0cfgDir/tmp_genesis.json $n0cfgDir/genesis.json + echo "--- Validating genesis..." $NODE_BIN $home0 validate-genesis @@ -182,7 +188,7 @@ echo echo "Command Line Access:" echo " * $NODE_BIN --home $hdir status" -$NODE_BIN $home0 start --api.enable true --grpc.address="0.0.0.0:9090" --grpc-web.enable=false --log_level trace > $log_path 2>&1 & +$NODE_BIN $home0 start --api.enable true --grpc.address="0.0.0.0:9090" --grpc-web.enable=false # Adds 1 sec to create the log and makes it easier to debug it on CI sleep 1 diff --git a/tools/tools.go b/tools/tools.go index f327d033..2cf01216 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -1,14 +1,14 @@ //go:build tools -// +build tools -// This file uses the recommended method for tracking developer tools in a Go -// module. -// -// REF: https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module package tools import ( + _ "github.com/bufbuild/buf/cmd/buf" + _ "github.com/cosmos/cosmos-proto/cmd/protoc-gen-go-pulsar" + _ "github.com/cosmos/gogoproto/protoc-gen-gocosmos" _ "github.com/golangci/golangci-lint/cmd/golangci-lint" + _ "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway" + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2" _ "github.com/mgechev/revive" _ "golang.org/x/tools/cmd/goimports" _ "google.golang.org/grpc/cmd/protoc-gen-go-grpc" diff --git a/x/oracle/abci.go b/x/oracle/abci.go index ee3c8932..9b5244aa 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -87,6 +87,8 @@ func CalcPrices(ctx sdk.Context, params types.Params, k keeper.Keeper) error { ballotDenomSlice := k.OrganizeBallotByDenom(ctx, validatorClaimMap) threshold := k.VoteThreshold(ctx).MulInt64(types.MaxVoteThresholdMultiplier).TruncateInt64() + ctx.Logger().Info("Endblocker log", "ballotDenomSlice", ballotDenomSlice) + // Iterate through ballots and update exchange rates; drop if not enough votes have been achieved. for _, ballotDenom := range ballotDenomSlice { // Increment Mandatory Win count if Denom in Mandatory list diff --git a/x/oracle/keeper/keeper.go b/x/oracle/keeper/keeper.go index 887f4591..fdac62df 100644 --- a/x/oracle/keeper/keeper.go +++ b/x/oracle/keeper/keeper.go @@ -14,6 +14,7 @@ import ( "github.com/ojo-network/ojo/util/metrics" "github.com/ojo-network/ojo/x/oracle/types" + "github.com/ojo-network/price-feeder/oracle" ) var ten = math.LegacyMustNewDecFromStr("10") @@ -29,6 +30,8 @@ type Keeper struct { distrKeeper types.DistributionKeeper StakingKeeper types.StakingKeeper + PriceFeederOracle *oracle.Oracle + distrName string telemetryEnabled bool // the address capable of executing a MsgUpdateParams message. Typically, this From 19b255ef9459b610545de674add1444fb3a07364 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Wed, 6 Mar 2024 11:09:32 -0500 Subject: [PATCH 02/27] fix preblocker init --- abci/proposal.go | 3 +-- app/app.go | 1 - pricefeeder/price-feeder.example.toml | 2 +- scripts/single-node.sh | 8 +------- x/oracle/abci.go | 2 ++ 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/abci/proposal.go b/abci/proposal.go index 24248407..a58664f2 100644 --- a/abci/proposal.go +++ b/abci/proposal.go @@ -61,7 +61,7 @@ func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler { voteExtensionsEnabled := VoteExtensionsEnabled(ctx) if voteExtensionsEnabled { - exchangeRateVotes, err := h.generateExchangeRateVotes(ctx, req.LocalLastCommit) + exchangeRateVotes, err := h.generateExchangeRateVotes(req.LocalLastCommit) if err != nil { return nil, errors.New("failed to generate exchange rate votes") } @@ -148,7 +148,6 @@ func (h *ProposalHandler) ProcessProposal() sdk.ProcessProposalHandler { } func (h *ProposalHandler) generateExchangeRateVotes( - ctx sdk.Context, ci cometabci.ExtendedCommitInfo, ) (votes []oracletypes.AggregateExchangeRateVote, err error) { for _, vote := range ci.Votes { diff --git a/app/app.go b/app/app.go index efac9f92..ee547cf4 100644 --- a/app/app.go +++ b/app/app.go @@ -759,7 +759,6 @@ func New( // initialize BaseApp app.SetInitChainer(app.InitChainer) - app.SetPreBlocker(app.PreBlocker) app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) app.setAnteHandler(txConfig) diff --git a/pricefeeder/price-feeder.example.toml b/pricefeeder/price-feeder.example.toml index 882dded8..af454e94 100644 --- a/pricefeeder/price-feeder.example.toml +++ b/pricefeeder/price-feeder.example.toml @@ -329,6 +329,6 @@ enable-hostname = true enable-hostname-label = true enable-service-label = true enabled = true -global-labels = [["chain_id", "ojo-testnet"]] +global-labels = [["chain_id", "ojotest-1"]] service-name = "price-feeder" prometheus-retention-time = 100 diff --git a/scripts/single-node.sh b/scripts/single-node.sh index 99a04067..460c1e55 100755 --- a/scripts/single-node.sh +++ b/scripts/single-node.sh @@ -17,7 +17,7 @@ PRICE_FEEDER_CONFIG_PATH="${CWD}/../pricefeeder/price-feeder.example.toml" export PRICE_FEEDER_CONFIG=$(realpath "$PRICE_FEEDER_CONFIG_PATH") export PRICE_FEEDER_CHAIN_CONFIG="FALSE" export PRICE_FEEDER_LOG_LEVEL="DEBUG" -export PRICE_FEEDER_ORACLE_TICK_TIME="5s" +export PRICE_FEEDER_ORACLE_TICK_TIME="1s" NODE_BIN="${1:-$CWD/../build/ojod}" @@ -142,12 +142,6 @@ if [[ ! -d "$hdir" ]]; then $NODE_BIN $home0 collect-gentxs > /dev/null - # copy centralized sequencer address into genesis.json - # Note: validator and sequencer are used interchangeably here - ADDRESS=$(jq -r '.address' $n0cfgDir/priv_validator_key.json) - PUB_KEY=$(jq -r '.pub_key' $n0cfgDir/priv_validator_key.json) - jq --argjson pubKey "$PUB_KEY" '.consensus["validators"]=[{"address": "'$ADDRESS'", "pub_key": $pubKey, "power": "1000000000000", "name": "Rollkit Sequencer"}]' $n0cfgDir/genesis.json > $n0cfgDir/tmp_genesis.json && mv $n0cfgDir/tmp_genesis.json $n0cfgDir/genesis.json - echo "--- Validating genesis..." $NODE_BIN $home0 validate-genesis diff --git a/x/oracle/abci.go b/x/oracle/abci.go index 9b5244aa..13c38632 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -83,6 +83,8 @@ func CalcPrices(ctx sdk.Context, params types.Params, k keeper.Keeper) error { k.ClearExchangeRates(ctx) + ctx.Logger().Info("Endblocker log", "validatorClaimMap", validatorClaimMap) + // NOTE: it filters out inactive or jailed validators ballotDenomSlice := k.OrganizeBallotByDenom(ctx, validatorClaimMap) threshold := k.VoteThreshold(ctx).MulInt64(types.MaxVoteThresholdMultiplier).TruncateInt64() From c839a04bfcb5774bc814c587288fca22d99f43ff Mon Sep 17 00:00:00 2001 From: rbajollari Date: Wed, 6 Mar 2024 18:17:16 -0500 Subject: [PATCH 03/27] use validator in pf config for vote extensions --- abci/preblock.go | 6 +----- abci/proposal.go | 3 +-- abci/voteextension.go | 11 ++++++----- pricefeeder/price-feeder.example.toml | 3 +++ pricefeeder/pricefeeder.go | 11 ++++++++++- scripts/single-node.sh | 2 +- x/oracle/abci.go | 4 ---- 7 files changed, 22 insertions(+), 18 deletions(-) diff --git a/abci/preblock.go b/abci/preblock.go index 7bd61da1..9d9f83f3 100644 --- a/abci/preblock.go +++ b/abci/preblock.go @@ -43,7 +43,7 @@ func (h *PreBlockHandler) PreBlocker() sdk.PreBlocker { h.logger.Error("failed to decode injected vote extension tx", "err", err) return nil, err } - h.logger.Info("PreBlocker injectedVoteExtTx", "tx", injectedVoteExtTx) + // set oracle exchange rate votes using the passed in context, which will make // these votes available in the current block. for _, exchangeRateVote := range injectedVoteExtTx.ExchangeRateVotes { @@ -51,10 +51,6 @@ func (h *PreBlockHandler) PreBlocker() sdk.PreBlocker { if err != nil { return nil, err } - h.logger.Info( - "setting oracle exchange rate vote", - "exchange rate vote", exchangeRateVote, - ) h.keeper.SetAggregateExchangeRateVote(ctx, valAddr, exchangeRateVote) } } diff --git a/abci/proposal.go b/abci/proposal.go index a58664f2..313dc98d 100644 --- a/abci/proposal.go +++ b/abci/proposal.go @@ -121,7 +121,6 @@ func (h *ProposalHandler) ProcessProposal() sdk.ProcessProposalHandler { h.logger.Error("failed to decode injected vote extension tx", "err", err) return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, nil } - h.logger.Info("ProcessProposal injectedVoteExtTx", "tx", injectedVoteExtTx) err := baseapp.ValidateVoteExtensions( ctx, h.valStore, @@ -164,7 +163,7 @@ func (h *ProposalHandler) generateExchangeRateVotes( ) return nil, err } - exchangeRateVote := oracletypes.NewAggregateExchangeRateVote(voteExt.ExchangeRates, vote.Validator.Address) + exchangeRateVote := oracletypes.NewAggregateExchangeRateVote(voteExt.ExchangeRates, voteExt.ValidatorAddress) votes = append(votes, exchangeRateVote) } diff --git a/abci/voteextension.go b/abci/voteextension.go index 540898b9..322765ea 100644 --- a/abci/voteextension.go +++ b/abci/voteextension.go @@ -16,8 +16,9 @@ import ( // OracleVoteExtension defines the canonical vote extension structure. type OracleVoteExtension struct { - Height int64 - ExchangeRates sdk.DecCoins + Height int64 + ExchangeRates sdk.DecCoins + ValidatorAddress sdk.ValAddress } type VoteExtHandler struct { @@ -66,7 +67,6 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return nil, err } prices := h.priceFeeder.Oracle.GetPrices() - h.logger.Info("Price feeder prices", "prices", prices) exchangeRatesStr := oracle.GenerateExchangeRatesString(prices) // Parse as DecCoins @@ -90,8 +90,9 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { } voteExt := OracleVoteExtension{ - Height: req.Height, - ExchangeRates: filteredDecCoins, + Height: req.Height, + ExchangeRates: filteredDecCoins, + ValidatorAddress: *h.priceFeeder.ValidatorAddress, } bz, err := json.Marshal(voteExt) diff --git a/pricefeeder/price-feeder.example.toml b/pricefeeder/price-feeder.example.toml index af454e94..9a1de3ef 100644 --- a/pricefeeder/price-feeder.example.toml +++ b/pricefeeder/price-feeder.example.toml @@ -319,6 +319,9 @@ read_timeout = "20s" verbose_cors = true write_timeout = "20s" +[account] +validator = "ojovaloper1zypqa76je7pxsdwkfah6mu9a583sju6x6tnq6w" + [rpc] grpc_endpoint = "localhost:9090" rpc_timeout = "100ms" diff --git a/pricefeeder/pricefeeder.go b/pricefeeder/pricefeeder.go index 3e059241..27971109 100644 --- a/pricefeeder/pricefeeder.go +++ b/pricefeeder/pricefeeder.go @@ -17,6 +17,7 @@ import ( "golang.org/x/sync/errgroup" "github.com/cosmos/cosmos-sdk/telemetry" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ojo-network/ojo/x/oracle/types" @@ -35,7 +36,8 @@ const ( ) type PriceFeeder struct { - Oracle *oracle.Oracle + Oracle *oracle.Oracle + ValidatorAddress *sdk.ValAddress } func (pf *PriceFeeder) Start(oracleParams types.Params) error { @@ -51,6 +53,13 @@ func (pf *PriceFeeder) Start(oracleParams types.Params) error { return err } + // set validator address + validatorAddr, err := sdk.ValAddressFromBech32(cfg.Account.Validator) + if err != nil { + return err + } + pf.ValidatorAddress = &validatorAddr + // listen for and trap any OS signal to gracefully shutdown and exit ctx, cancel := context.WithCancel(context.TODO()) g, ctx := errgroup.WithContext(ctx) diff --git a/scripts/single-node.sh b/scripts/single-node.sh index 460c1e55..d089aea9 100755 --- a/scripts/single-node.sh +++ b/scripts/single-node.sh @@ -182,7 +182,7 @@ echo echo "Command Line Access:" echo " * $NODE_BIN --home $hdir status" -$NODE_BIN $home0 start --api.enable true --grpc.address="0.0.0.0:9090" --grpc-web.enable=false +$NODE_BIN $home0 start --api.enable true --grpc.address="0.0.0.0:9090" --grpc-web.enable=false --log_level trace > $log_path 2>&1 & # Adds 1 sec to create the log and makes it easier to debug it on CI sleep 1 diff --git a/x/oracle/abci.go b/x/oracle/abci.go index 13c38632..ee3c8932 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -83,14 +83,10 @@ func CalcPrices(ctx sdk.Context, params types.Params, k keeper.Keeper) error { k.ClearExchangeRates(ctx) - ctx.Logger().Info("Endblocker log", "validatorClaimMap", validatorClaimMap) - // NOTE: it filters out inactive or jailed validators ballotDenomSlice := k.OrganizeBallotByDenom(ctx, validatorClaimMap) threshold := k.VoteThreshold(ctx).MulInt64(types.MaxVoteThresholdMultiplier).TruncateInt64() - ctx.Logger().Info("Endblocker log", "ballotDenomSlice", ballotDenomSlice) - // Iterate through ballots and update exchange rates; drop if not enough votes have been achieved. for _, ballotDenom := range ballotDenomSlice { // Increment Mandatory Win count if Denom in Mandatory list From b4f7f2536194264fb21667fc5cbcdfc3f86294ea Mon Sep 17 00:00:00 2001 From: rbajollari Date: Wed, 6 Mar 2024 18:22:29 -0500 Subject: [PATCH 04/27] lint --- abci/voteextension.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/abci/voteextension.go b/abci/voteextension.go index 322765ea..85d59398 100644 --- a/abci/voteextension.go +++ b/abci/voteextension.go @@ -50,7 +50,8 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { "err", r, ) - resp, err = &cometabci.ResponseExtendVote{VoteExtension: []byte{}}, fmt.Errorf("recovered application panic in ExtendVote: %v", r) + resp, err = &cometabci.ResponseExtendVote{VoteExtension: []byte{}}, + fmt.Errorf("recovered application panic in ExtendVote: %v", r) } }() @@ -62,7 +63,7 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { // Get prices from Oracle Keeper's pricefeeder and generate vote msg if h.priceFeeder.Oracle == nil { - err := fmt.Errorf("Price Feeder Oracle not set") + err := fmt.Errorf("price feeder oracle not set") h.logger.Error(err.Error()) return nil, err } @@ -114,7 +115,10 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { } func (h *VoteExtHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { - return func(ctx sdk.Context, req *cometabci.RequestVerifyVoteExtension) (*cometabci.ResponseVerifyVoteExtension, error) { + return func(ctx sdk.Context, req *cometabci.RequestVerifyVoteExtension) ( + *cometabci.ResponseVerifyVoteExtension, + error, + ) { if req == nil { err := fmt.Errorf("verify vote extension handler received a nil request") h.logger.Error(err.Error()) From c782b75a213d642da45bc94c9f149d4957313c90 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Thu, 7 Mar 2024 11:20:35 -0500 Subject: [PATCH 05/27] add verification in process proposal --- abci/proposal.go | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/abci/proposal.go b/abci/proposal.go index 313dc98d..71c41361 100644 --- a/abci/proposal.go +++ b/abci/proposal.go @@ -57,7 +57,6 @@ func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler { } proposalTxs := req.Txs - h.logger.Info("proposalTxs before", "txs", proposalTxs) voteExtensionsEnabled := VoteExtensionsEnabled(ctx) if voteExtensionsEnabled { @@ -83,8 +82,6 @@ func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler { proposalTxs = append([][]byte{bz}, proposalTxs...) } - h.logger.Info("proposalTxs after", "txs", proposalTxs) - h.logger.Info( "prepared proposal", "txs", len(proposalTxs), @@ -134,6 +131,14 @@ func (h *ProposalHandler) ProcessProposal() sdk.ProcessProposalHandler { // Verify the proposer's oracle exchange rate votes by computing the same // calculation and comparing the results. + exchangeRateVotes, err := h.generateExchangeRateVotes(injectedVoteExtTx.ExtendedCommitInfo) + if err != nil { + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, + errors.New("failed to generate exchange rate votes") + } + if err := h.compareExchangeRateVotes(injectedVoteExtTx.ExchangeRateVotes, exchangeRateVotes); err != nil { + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, err + } } h.logger.Info( @@ -169,3 +174,29 @@ func (h *ProposalHandler) generateExchangeRateVotes( return votes, nil } + +func (h *ProposalHandler) compareExchangeRateVotes( + voteExtVotes []oracletypes.AggregateExchangeRateVote, + generatedVotes []oracletypes.AggregateExchangeRateVote, +) (err error) { + // h.logger.Info("voteExtVotes", "votes", voteExtVotes) + // h.logger.Info("generatedVotes", "votes", generatedVotes) + // if len(voteExtVotes) != len(generatedVotes) { + // err = fmt.Errorf( + // "failed to process proposal due to unequal amount of votes in vote extension and extended commit info", + // ) + // h.logger.Error(err.Error()) + // return err + // } + + // for i, vote := range voteExtVotes { + // if vote.Voter != generatedVotes[i].Voter || vote.ExchangeRates.Equal(generatedVotes[i].ExchangeRates) { + // err = fmt.Errorf( + // "failed to process proposal due to mismatch in votes bewteen vote extension and extended commit info", + // ) + // h.logger.Error(err.Error()) + // return err + // } + // } + return nil +} From d6acf4cc37fbcdaff17c72f5b458a8d3e5fd74c9 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Thu, 7 Mar 2024 14:53:19 -0500 Subject: [PATCH 06/27] process proposal verifaction --- abci/proposal.go | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/abci/proposal.go b/abci/proposal.go index 71c41361..4667e38d 100644 --- a/abci/proposal.go +++ b/abci/proposal.go @@ -136,8 +136,9 @@ func (h *ProposalHandler) ProcessProposal() sdk.ProcessProposalHandler { return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, errors.New("failed to generate exchange rate votes") } - if err := h.compareExchangeRateVotes(injectedVoteExtTx.ExchangeRateVotes, exchangeRateVotes); err != nil { - return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, err + if len(injectedVoteExtTx.ExchangeRateVotes) != len(exchangeRateVotes) { + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, + errors.New("number of votes in vote extension and extended commit info are not equal") } } @@ -174,29 +175,3 @@ func (h *ProposalHandler) generateExchangeRateVotes( return votes, nil } - -func (h *ProposalHandler) compareExchangeRateVotes( - voteExtVotes []oracletypes.AggregateExchangeRateVote, - generatedVotes []oracletypes.AggregateExchangeRateVote, -) (err error) { - // h.logger.Info("voteExtVotes", "votes", voteExtVotes) - // h.logger.Info("generatedVotes", "votes", generatedVotes) - // if len(voteExtVotes) != len(generatedVotes) { - // err = fmt.Errorf( - // "failed to process proposal due to unequal amount of votes in vote extension and extended commit info", - // ) - // h.logger.Error(err.Error()) - // return err - // } - - // for i, vote := range voteExtVotes { - // if vote.Voter != generatedVotes[i].Voter || vote.ExchangeRates.Equal(generatedVotes[i].ExchangeRates) { - // err = fmt.Errorf( - // "failed to process proposal due to mismatch in votes bewteen vote extension and extended commit info", - // ) - // h.logger.Error(err.Error()) - // return err - // } - // } - return nil -} From d1ec5de6e3077619e3421e4a878650753d77cb34 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Thu, 7 Mar 2024 19:38:45 -0500 Subject: [PATCH 07/27] setup oracle abci integration test suite --- app/app.go | 6 +- x/oracle/abci/abci_test.go | 29 ++++++++ x/oracle/{abci.go => abci/endblocker.go} | 2 +- .../{abci_test.go => abci/endblocker_test.go} | 71 ++++++------------- .../oracle/abci/preblocker.go | 0 x/oracle/abci/preblocker_test.go | 5 ++ {abci => x/oracle/abci}/proposal.go | 4 +- x/oracle/abci/proposal_test.go | 9 +++ {abci => x/oracle/abci}/util.go | 0 {abci => x/oracle/abci}/voteextension.go | 0 x/oracle/abci/voteextension_test.go | 9 +++ x/oracle/genesis_test.go | 22 +++++- x/oracle/keeper/msg_server_test.go | 10 +-- x/oracle/module.go | 3 +- 14 files changed, 108 insertions(+), 62 deletions(-) create mode 100644 x/oracle/abci/abci_test.go rename x/oracle/{abci.go => abci/endblocker.go} (99%) rename x/oracle/{abci_test.go => abci/endblocker_test.go} (92%) rename abci/preblock.go => x/oracle/abci/preblocker.go (100%) create mode 100644 x/oracle/abci/preblocker_test.go rename {abci => x/oracle/abci}/proposal.go (97%) create mode 100644 x/oracle/abci/proposal_test.go rename {abci => x/oracle/abci}/util.go (100%) rename {abci => x/oracle/abci}/voteextension.go (100%) create mode 100644 x/oracle/abci/voteextension_test.go diff --git a/app/app.go b/app/app.go index ee547cf4..6133f3c7 100644 --- a/app/app.go +++ b/app/app.go @@ -119,8 +119,8 @@ import ( airdropkeeper "github.com/ojo-network/ojo/x/airdrop/keeper" airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" - ojoabci "github.com/ojo-network/ojo/abci" "github.com/ojo-network/ojo/pricefeeder" + ojoabci "github.com/ojo-network/ojo/x/oracle/abci" customante "github.com/ojo-network/ojo/ante" ) @@ -733,8 +733,8 @@ func New( app.OracleKeeper, app.StakingKeeper, ) - app.SetPrepareProposal(proposalHandler.PrepareProposal()) - app.SetProcessProposal(proposalHandler.ProcessProposal()) + app.SetPrepareProposal(proposalHandler.PrepareProposalHandler()) + app.SetProcessProposal(proposalHandler.ProcessProposalHandler()) preBlockHandler := ojoabci.NewPreBlockHandler( app.Logger(), diff --git a/x/oracle/abci/abci_test.go b/x/oracle/abci/abci_test.go new file mode 100644 index 00000000..1191c773 --- /dev/null +++ b/x/oracle/abci/abci_test.go @@ -0,0 +1,29 @@ +package abci_test + +import ( + "testing" + + "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ojo-network/ojo/tests/integration" + "github.com/stretchr/testify/suite" + + ojoapp "github.com/ojo-network/ojo/app" +) + +type IntegrationTestSuite struct { + suite.Suite + + ctx sdk.Context + app *ojoapp.App + keys []integration.TestValidatorKey +} + +func (s *IntegrationTestSuite) SetupTest() { + s.app, s.ctx, s.keys = integration.SetupAppWithContext(s.T()) + s.app.OracleKeeper.SetVoteThreshold(s.ctx, math.LegacyMustNewDecFromStr("0.4")) +} + +func TestAbciTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/oracle/abci.go b/x/oracle/abci/endblocker.go similarity index 99% rename from x/oracle/abci.go rename to x/oracle/abci/endblocker.go index ee3c8932..d3ac138b 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci/endblocker.go @@ -1,4 +1,4 @@ -package oracle +package abci import ( "context" diff --git a/x/oracle/abci_test.go b/x/oracle/abci/endblocker_test.go similarity index 92% rename from x/oracle/abci_test.go rename to x/oracle/abci/endblocker_test.go index 4b2ad842..37e3bc50 100644 --- a/x/oracle/abci_test.go +++ b/x/oracle/abci/endblocker_test.go @@ -1,38 +1,15 @@ -package oracle_test +package abci_test import ( - "testing" - "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/stretchr/testify/suite" - ojoapp "github.com/ojo-network/ojo/app" appparams "github.com/ojo-network/ojo/app/params" - "github.com/ojo-network/ojo/tests/integration" "github.com/ojo-network/ojo/util/decmath" - "github.com/ojo-network/ojo/x/oracle" + "github.com/ojo-network/ojo/x/oracle/abci" "github.com/ojo-network/ojo/x/oracle/types" ) -const ( - displayDenom string = appparams.DisplayDenom - bondDenom string = appparams.BondDenom -) - -type IntegrationTestSuite struct { - suite.Suite - - ctx sdk.Context - app *ojoapp.App - keys []integration.TestValidatorKey -} - -func (s *IntegrationTestSuite) SetupTest() { - s.app, s.ctx, s.keys = integration.SetupAppWithContext(s.T()) - s.app.OracleKeeper.SetVoteThreshold(s.ctx, math.LegacyMustNewDecFromStr("0.4")) -} - func createVotes(hash string, val sdk.ValAddress, rates sdk.DecCoins, blockHeight uint64) (types.AggregateExchangeRatePrevote, types.AggregateExchangeRateVote) { preVote := types.AggregateExchangeRatePrevote{ Hash: hash, @@ -91,13 +68,13 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr1, val1PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr3, val3PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr1, val1Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr3, val3Votes) - err := oracle.EndBlocker(ctx, app.OracleKeeper) + err := abci.EndBlocker(ctx, app.OracleKeeper) s.Require().NoError(err) for _, denom := range app.OracleKeeper.AcceptList(ctx) { @@ -114,11 +91,11 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { val2PreVotes.SubmitBlock = h app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) for _, denom := range app.OracleKeeper.AcceptList(ctx) { rate, err := app.OracleKeeper.GetExchangeRate(ctx, denom.SymbolDenom) @@ -135,12 +112,12 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr3, val3PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr3, val3Votes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) for _, denom := range app.OracleKeeper.AcceptList(ctx) { rate, err := app.OracleKeeper.GetExchangeRate(ctx, denom.SymbolDenom) @@ -164,12 +141,12 @@ func (s *IntegrationTestSuite) TestEndBlockerVoteThreshold() { app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr1, val1PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr1, val1Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) rate, err := app.OracleKeeper.GetExchangeRate(ctx, "ojo") s.Require().NoError(err) @@ -187,11 +164,11 @@ func (s *IntegrationTestSuite) TestEndBlockerValidatorRewards() { // start test in new slash window ctx = ctx.WithBlockHeight(int64(app.OracleKeeper.SlashWindow(ctx))) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) app.OracleKeeper.SetMandatoryList(ctx, types.DenomList{ { - BaseDenom: bondDenom, + BaseDenom: appparams.BondDenom, SymbolDenom: appparams.DisplayDenom, Exponent: uint32(6), }, @@ -230,13 +207,13 @@ func (s *IntegrationTestSuite) TestEndBlockerValidatorRewards() { app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr1, val1PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr3, val3PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr1, val1Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr3, val3Votes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) currRewards1, err := app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddr1) s.Require().NoError(err) @@ -289,13 +266,13 @@ func (s *IntegrationTestSuite) TestEndBlockerValidatorRewards() { app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr1, val1PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr3, val3PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr1, val1Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr3, val3Votes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) currRewards1, err = app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddr1) s.Require().NoError(err) @@ -321,13 +298,13 @@ func (s *IntegrationTestSuite) TestEndBlockerValidatorRewards() { app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr1, val1PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr2, val2PreVotes) app.OracleKeeper.SetAggregateExchangeRatePrevote(ctx, valAddr3, val3PreVotes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) ctx = ctx.WithBlockHeight(ctx.BlockHeight() + voteBlockDiff) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr1, val1Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr2, val2Votes) app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr3, val3Votes) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) currRewards1, err = app.DistrKeeper.GetValidatorCurrentRewards(ctx, valAddr1) s.Require().NoError(err) @@ -394,7 +371,7 @@ func (s *IntegrationTestSuite) TestEndblockerHistoracle() { Voter: valAddr1.String(), } app.OracleKeeper.SetAggregateExchangeRateVote(ctx, valAddr1, vote) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) } for denom, denomRates := range exchangeRates { @@ -478,12 +455,12 @@ func (s *IntegrationTestSuite) TestUpdateOracleParams() { s.Require().Len(plans, 2) // Check Vote Threshold was updated by first plan - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) s.Require().Equal(math.LegacyNewDecWithPrec(40, 2), app.OracleKeeper.VoteThreshold(ctx)) // Check Vote Threshold was updated by second plan in next block ctx = ctx.WithBlockHeight(blockHeight + 1) - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) s.Require().Equal(math.LegacyNewDecWithPrec(50, 2), app.OracleKeeper.VoteThreshold(ctx)) // Schedule param update plan for current block height and then cancel it @@ -508,10 +485,6 @@ func (s *IntegrationTestSuite) TestUpdateOracleParams() { s.Require().Len(plans, 0) // Check Vote Threshold wasn't updated - oracle.EndBlocker(ctx, app.OracleKeeper) + abci.EndBlocker(ctx, app.OracleKeeper) s.Require().Equal(math.LegacyNewDecWithPrec(50, 2), app.OracleKeeper.VoteThreshold(ctx)) } - -func TestOracleTestSuite(t *testing.T) { - suite.Run(t, new(IntegrationTestSuite)) -} diff --git a/abci/preblock.go b/x/oracle/abci/preblocker.go similarity index 100% rename from abci/preblock.go rename to x/oracle/abci/preblocker.go diff --git a/x/oracle/abci/preblocker_test.go b/x/oracle/abci/preblocker_test.go new file mode 100644 index 00000000..7892e62e --- /dev/null +++ b/x/oracle/abci/preblocker_test.go @@ -0,0 +1,5 @@ +package abci_test + +func (s *IntegrationTestSuite) TestPreBlocker() { + +} diff --git a/abci/proposal.go b/x/oracle/abci/proposal.go similarity index 97% rename from abci/proposal.go rename to x/oracle/abci/proposal.go index 4667e38d..6d171f68 100644 --- a/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -34,7 +34,7 @@ func NewProposalHandler(logger log.Logger, keeper keeper.Keeper, valStore baseap } } -func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler { +func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *cometabci.RequestPrepareProposal) (*cometabci.ResponsePrepareProposal, error) { if req == nil { err := fmt.Errorf("prepare proposal received a nil request") @@ -94,7 +94,7 @@ func (h *ProposalHandler) PrepareProposal() sdk.PrepareProposalHandler { } } -func (h *ProposalHandler) ProcessProposal() sdk.ProcessProposalHandler { +func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return func(ctx sdk.Context, req *cometabci.RequestProcessProposal) (*cometabci.ResponseProcessProposal, error) { if req == nil { err := fmt.Errorf("process proposal received a nil request") diff --git a/x/oracle/abci/proposal_test.go b/x/oracle/abci/proposal_test.go new file mode 100644 index 00000000..44e7f9a2 --- /dev/null +++ b/x/oracle/abci/proposal_test.go @@ -0,0 +1,9 @@ +package abci_test + +func (s *IntegrationTestSuite) TestPrepareProposalHandler() { + +} + +func (s *IntegrationTestSuite) TestProcessProposalHandler() { + +} diff --git a/abci/util.go b/x/oracle/abci/util.go similarity index 100% rename from abci/util.go rename to x/oracle/abci/util.go diff --git a/abci/voteextension.go b/x/oracle/abci/voteextension.go similarity index 100% rename from abci/voteextension.go rename to x/oracle/abci/voteextension.go diff --git a/x/oracle/abci/voteextension_test.go b/x/oracle/abci/voteextension_test.go new file mode 100644 index 00000000..ed03ec94 --- /dev/null +++ b/x/oracle/abci/voteextension_test.go @@ -0,0 +1,9 @@ +package abci_test + +func (s *IntegrationTestSuite) TestExtendVoteHandler() { + +} + +func (s *IntegrationTestSuite) TestVerifyVoteExtensionHandler() { + +} diff --git a/x/oracle/genesis_test.go b/x/oracle/genesis_test.go index 9b348412..0a6a23c1 100644 --- a/x/oracle/genesis_test.go +++ b/x/oracle/genesis_test.go @@ -2,10 +2,15 @@ package oracle_test import ( "gotest.tools/v3/assert" + "testing" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + appparams "github.com/ojo-network/ojo/app/params" + "github.com/ojo-network/ojo/tests/integration" + "github.com/stretchr/testify/suite" + ojoapp "github.com/ojo-network/ojo/app" "github.com/ojo-network/ojo/x/oracle" "github.com/ojo-network/ojo/x/oracle/types" ) @@ -16,8 +21,19 @@ const ( denom = "ojo" ) +type IntegrationTestSuite struct { + suite.Suite + + ctx sdk.Context + app *ojoapp.App +} + var exchangeRate = math.LegacyMustNewDecFromStr("8.8") +func (s *IntegrationTestSuite) SetupTest() { + s.app, s.ctx, _ = integration.SetupAppWithContext(s.T()) +} + func (s *IntegrationTestSuite) TestGenesis_InitGenesis() { keeper, ctx := s.app.OracleKeeper, s.ctx @@ -157,7 +173,7 @@ func (s *IntegrationTestSuite) TestGenesis_ExportGenesis() { } exchangeRates := sdk.DecCoins{ { - Denom: displayDenom, + Denom: appparams.DisplayDenom, Amount: exchangeRate, }, } @@ -232,3 +248,7 @@ func (s *IntegrationTestSuite) TestGenesis_ExportGenesis() { assert.DeepEqual(s.T(), historicPrices, result.HistoricPrices) assert.DeepEqual(s.T(), medianDeviations, result.MedianDeviations) } + +func TestOracleTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/oracle/keeper/msg_server_test.go b/x/oracle/keeper/msg_server_test.go index 08687ef8..075816c5 100644 --- a/x/oracle/keeper/msg_server_test.go +++ b/x/oracle/keeper/msg_server_test.go @@ -8,7 +8,7 @@ import ( "cosmossdk.io/errors" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ojo-network/ojo/x/oracle" + "github.com/ojo-network/ojo/x/oracle/abci" "github.com/ojo-network/ojo/x/oracle/types" oracletypes "github.com/ojo-network/ojo/x/oracle/types" ) @@ -420,7 +420,7 @@ func (s *IntegrationTestSuite) TestMsgServer_UpdateGovParams() { err := tc.req.ValidateBasic() if err == nil { _, err = s.msgServer.GovUpdateParams(s.ctx, tc.req) - oracle.EndBlocker(s.ctx, s.app.OracleKeeper) + abci.EndBlocker(s.ctx, s.app.OracleKeeper) } if tc.expectErr { s.Require().ErrorContains(err, tc.errMsg) @@ -762,7 +762,7 @@ func (s *IntegrationTestSuite) TestMsgServer_GovAddDenom() { err := tc.req.ValidateBasic() if err == nil { _, err = s.msgServer.GovAddDenoms(s.ctx, tc.req) - oracle.EndBlocker(s.ctx, s.app.OracleKeeper) + abci.EndBlocker(s.ctx, s.app.OracleKeeper) } if tc.expectErr { s.Require().ErrorContains(err, tc.errMsg) @@ -986,7 +986,7 @@ func (s *IntegrationTestSuite) TestMsgServer_GovRemoveCurrencyPairProviders() { err := tc.req.ValidateBasic() if err == nil { _, err = s.msgServer.GovRemoveCurrencyPairProviders(s.ctx, tc.req) - oracle.EndBlocker(s.ctx, s.app.OracleKeeper) + abci.EndBlocker(s.ctx, s.app.OracleKeeper) } if tc.expectErr { @@ -1113,7 +1113,7 @@ func (s *IntegrationTestSuite) TestMsgServer_GovRemoveCurrencyDeviationThreshold err := tc.req.ValidateBasic() if err == nil { _, err = s.msgServer.GovRemoveCurrencyDeviationThresholds(s.ctx, tc.req) - oracle.EndBlocker(s.ctx, s.app.OracleKeeper) + abci.EndBlocker(s.ctx, s.app.OracleKeeper) } if tc.expectErr { diff --git a/x/oracle/module.go b/x/oracle/module.go index 5caef0f7..ac15db2a 100644 --- a/x/oracle/module.go +++ b/x/oracle/module.go @@ -17,6 +17,7 @@ import ( "github.com/spf13/cobra" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + oracleabci "github.com/ojo-network/ojo/x/oracle/abci" "github.com/ojo-network/ojo/x/oracle/client/cli" "github.com/ojo-network/ojo/x/oracle/keeper" simulation "github.com/ojo-network/ojo/x/oracle/simulations" @@ -169,7 +170,7 @@ func (am AppModule) BeginBlock(_ context.Context) {} // EndBlock executes all ABCI EndBlock logic respective to the x/oracle module. // It returns no validator updates. func (am AppModule) EndBlock(ctx context.Context) ([]abci.ValidatorUpdate, error) { - if err := EndBlocker(ctx, am.keeper); err != nil { + if err := oracleabci.EndBlocker(ctx, am.keeper); err != nil { panic(err) } From 81cbe3cc05ead22a9d8915675c1da7d3f2606e54 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Mon, 11 Mar 2024 11:03:58 -0400 Subject: [PATCH 08/27] use vote extension signer for exchange rate generation --- app/app.go | 8 +-- pricefeeder/price-feeder.example.toml | 3 - pricefeeder/pricefeeder.go | 11 +--- x/oracle/abci/abci_test.go | 54 ++++++++++++++++ x/oracle/abci/proposal.go | 91 +++++++++++++++++++++------ x/oracle/abci/voteextension.go | 20 +++--- x/oracle/abci/voteextension_test.go | 54 ++++++++++++++++ 7 files changed, 193 insertions(+), 48 deletions(-) diff --git a/app/app.go b/app/app.go index 6133f3c7..54424dc1 100644 --- a/app/app.go +++ b/app/app.go @@ -120,7 +120,7 @@ import ( airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" "github.com/ojo-network/ojo/pricefeeder" - ojoabci "github.com/ojo-network/ojo/x/oracle/abci" + oracleabci "github.com/ojo-network/ojo/x/oracle/abci" customante "github.com/ojo-network/ojo/ante" ) @@ -728,7 +728,7 @@ func New( app.StateSimulationManager = module.NewSimulationManagerFromAppModules(app.mm.Modules, overrideModules) app.StateSimulationManager.RegisterStoreDecoders() - proposalHandler := ojoabci.NewProposalHandler( + proposalHandler := oracleabci.NewProposalHandler( app.Logger(), app.OracleKeeper, app.StakingKeeper, @@ -736,7 +736,7 @@ func New( app.SetPrepareProposal(proposalHandler.PrepareProposalHandler()) app.SetProcessProposal(proposalHandler.ProcessProposalHandler()) - preBlockHandler := ojoabci.NewPreBlockHandler( + preBlockHandler := oracleabci.NewPreBlockHandler( app.Logger(), app.OracleKeeper, ) @@ -744,7 +744,7 @@ func New( // initialize empty price feeder object to pass reference into vote extension handler app.PriceFeeder = &pricefeeder.PriceFeeder{} - voteExtensionsHandler := ojoabci.NewVoteExtensionHandler( + voteExtensionsHandler := oracleabci.NewVoteExtensionHandler( app.Logger(), app.OracleKeeper, app.PriceFeeder, diff --git a/pricefeeder/price-feeder.example.toml b/pricefeeder/price-feeder.example.toml index 9a1de3ef..af454e94 100644 --- a/pricefeeder/price-feeder.example.toml +++ b/pricefeeder/price-feeder.example.toml @@ -319,9 +319,6 @@ read_timeout = "20s" verbose_cors = true write_timeout = "20s" -[account] -validator = "ojovaloper1zypqa76je7pxsdwkfah6mu9a583sju6x6tnq6w" - [rpc] grpc_endpoint = "localhost:9090" rpc_timeout = "100ms" diff --git a/pricefeeder/pricefeeder.go b/pricefeeder/pricefeeder.go index 27971109..3e059241 100644 --- a/pricefeeder/pricefeeder.go +++ b/pricefeeder/pricefeeder.go @@ -17,7 +17,6 @@ import ( "golang.org/x/sync/errgroup" "github.com/cosmos/cosmos-sdk/telemetry" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ojo-network/ojo/x/oracle/types" @@ -36,8 +35,7 @@ const ( ) type PriceFeeder struct { - Oracle *oracle.Oracle - ValidatorAddress *sdk.ValAddress + Oracle *oracle.Oracle } func (pf *PriceFeeder) Start(oracleParams types.Params) error { @@ -53,13 +51,6 @@ func (pf *PriceFeeder) Start(oracleParams types.Params) error { return err } - // set validator address - validatorAddr, err := sdk.ValAddressFromBech32(cfg.Account.Validator) - if err != nil { - return err - } - pf.ValidatorAddress = &validatorAddr - // listen for and trap any OS signal to gracefully shutdown and exit ctx, cancel := context.WithCancel(context.TODO()) g, ctx := errgroup.WithContext(ctx) diff --git a/x/oracle/abci/abci_test.go b/x/oracle/abci/abci_test.go index 1191c773..05d85222 100644 --- a/x/oracle/abci/abci_test.go +++ b/x/oracle/abci/abci_test.go @@ -1,14 +1,22 @@ package abci_test import ( + // "context" "testing" + // "time" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ojo-network/ojo/tests/integration" + // "github.com/rs/zerolog" "github.com/stretchr/testify/suite" ojoapp "github.com/ojo-network/ojo/app" + // "github.com/ojo-network/ojo/pricefeeder" + // "github.com/ojo-network/price-feeder/oracle" + // "github.com/ojo-network/price-feeder/oracle/client" + // "github.com/ojo-network/price-feeder/oracle/provider" + // "github.com/ojo-network/price-feeder/oracle/types" ) type IntegrationTestSuite struct { @@ -27,3 +35,49 @@ func (s *IntegrationTestSuite) SetupTest() { func TestAbciTestSuite(t *testing.T) { suite.Run(t, new(IntegrationTestSuite)) } + +// func MockPriceFeeder(ctx context.Context) *pricefeeder.PriceFeeder { +// providers := make(map[types.ProviderName][]types.CurrencyPair) +// deviations := make(map[string]math.LegacyDec) +// providerEndpointsMap := make(map[types.ProviderName]provider.Endpoint) + +// oracle := oracle.New( +// zerolog.Nop(), +// client.OracleClient{}, +// providers, +// time.Second*10, +// deviations, +// providerEndpointsMap, +// false, +// ) + +// oracle.SetPrices(ctx) + +// return &pricefeeder.PriceFeeder{ +// Oracle: oracle, +// } +// } + +// type MockProvider struct {} + +// func (mp *MockProvider) GetTickerPrices(pairs ...types.CurrencyPair) (types.CurrencyPairTickers, error) { +// tickerPrices := make(types.CurrencyPairTickers, len(pairs)) + +// } + +// func (mp *MockProvider) GetCandlePrices(pairs ...types.CurrencyPair) (types.CurrencyPairCandles, error) { + +// } + +// func NewMockProvider() MockProvider { +// ojoPair := types.CurrencyPair{ +// Base: "OJO", +// Quote: "USD", +// Address: "OJOADDRESS", +// } +// usdcPair := types.CurrencyPair{ +// Base: "USDC", +// Quote: "USD", +// Address: "USDCADDRESS", +// } +// } diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index 6d171f68..ad401914 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -4,14 +4,16 @@ import ( "encoding/json" "errors" "fmt" + "sort" "cosmossdk.io/log" cometabci "github.com/cometbft/cometbft/abci/types" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - "github.com/ojo-network/ojo/x/oracle/keeper" + oraclekeeper "github.com/ojo-network/ojo/x/oracle/keeper" oracletypes "github.com/ojo-network/ojo/x/oracle/types" ) @@ -21,16 +23,20 @@ type AggregateExchangeRateVotes struct { } type ProposalHandler struct { - logger log.Logger - keeper keeper.Keeper - valStore baseapp.ValidatorStore + logger log.Logger + oracleKeeper oraclekeeper.Keeper + stakingKeeper *stakingkeeper.Keeper } -func NewProposalHandler(logger log.Logger, keeper keeper.Keeper, valStore baseapp.ValidatorStore) *ProposalHandler { +func NewProposalHandler( + logger log.Logger, + oracleKeeper oraclekeeper.Keeper, + stakingKeeper *stakingkeeper.Keeper, +) *ProposalHandler { return &ProposalHandler{ - logger: logger, - keeper: keeper, - valStore: valStore, + logger: logger, + oracleKeeper: oracleKeeper, + stakingKeeper: stakingKeeper, } } @@ -42,7 +48,7 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return nil, err } - err := baseapp.ValidateVoteExtensions(ctx, h.valStore, req.Height, ctx.ChainID(), req.LocalLastCommit) + err := baseapp.ValidateVoteExtensions(ctx, h.stakingKeeper, req.Height, ctx.ChainID(), req.LocalLastCommit) if err != nil { return nil, err } @@ -60,9 +66,9 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { voteExtensionsEnabled := VoteExtensionsEnabled(ctx) if voteExtensionsEnabled { - exchangeRateVotes, err := h.generateExchangeRateVotes(req.LocalLastCommit) + exchangeRateVotes, err := h.generateExchangeRateVotes(ctx, req.LocalLastCommit) if err != nil { - return nil, errors.New("failed to generate exchange rate votes") + return nil, err } injectedVoteExtTx := AggregateExchangeRateVotes{ @@ -120,7 +126,7 @@ func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { } err := baseapp.ValidateVoteExtensions( ctx, - h.valStore, + h.stakingKeeper, req.Height, ctx.ChainID(), injectedVoteExtTx.ExtendedCommitInfo, @@ -131,14 +137,12 @@ func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { // Verify the proposer's oracle exchange rate votes by computing the same // calculation and comparing the results. - exchangeRateVotes, err := h.generateExchangeRateVotes(injectedVoteExtTx.ExtendedCommitInfo) + exchangeRateVotes, err := h.generateExchangeRateVotes(ctx, injectedVoteExtTx.ExtendedCommitInfo) if err != nil { - return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, - errors.New("failed to generate exchange rate votes") + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, err } - if len(injectedVoteExtTx.ExchangeRateVotes) != len(exchangeRateVotes) { - return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, - errors.New("number of votes in vote extension and extended commit info are not equal") + if err := h.verifyExchangeRateVotes(injectedVoteExtTx.ExchangeRateVotes, exchangeRateVotes); err != nil { + return &cometabci.ResponseProcessProposal{Status: cometabci.ResponseProcessProposal_REJECT}, err } } @@ -153,6 +157,7 @@ func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { } func (h *ProposalHandler) generateExchangeRateVotes( + ctx sdk.Context, ci cometabci.ExtendedCommitInfo, ) (votes []oracletypes.AggregateExchangeRateVote, err error) { for _, vote := range ci.Votes { @@ -165,13 +170,59 @@ func (h *ProposalHandler) generateExchangeRateVotes( h.logger.Error( "failed to decode vote extension", "err", err, - "validator", fmt.Sprintf("%x", vote.Validator.Address), ) return nil, err } - exchangeRateVote := oracletypes.NewAggregateExchangeRateVote(voteExt.ExchangeRates, voteExt.ValidatorAddress) + + var valConsAddr sdk.ConsAddress + if err := valConsAddr.Unmarshal(vote.Validator.Address); err != nil { + h.logger.Error( + "failed to unmarshal validator consensus address", + "err", err, + ) + return nil, err + } + val, err := h.stakingKeeper.GetValidatorByConsAddr(ctx, valConsAddr) + if err != nil { + h.logger.Error( + "failed to get consensus validator from staking keeper", + "err", err, + ) + return nil, err + } + valAddr, err := sdk.ValAddressFromBech32(val.OperatorAddress) + if err != nil { + return nil, err + } + + exchangeRateVote := oracletypes.NewAggregateExchangeRateVote(voteExt.ExchangeRates, valAddr) votes = append(votes, exchangeRateVote) } + // sort votes so they are verified in the same order in ProcessProposalHandler + sort.Slice(votes, func(i, j int) bool { + return votes[i].Voter < votes[j].Voter + }) + return votes, nil } + +func (h *ProposalHandler) verifyExchangeRateVotes( + injectedVotes []oracletypes.AggregateExchangeRateVote, + generatedVotes []oracletypes.AggregateExchangeRateVote, +) error { + if len(injectedVotes) != len(generatedVotes) { + return errors.New("number of exchange rate votes in vote extension and extended commit info are not equal") + } + + for i := range injectedVotes { + injectedVote := injectedVotes[i] + generatedVote := generatedVotes[i] + + if injectedVote.Voter != generatedVote.Voter || !injectedVote.ExchangeRates.Equal(generatedVote.ExchangeRates) { + return errors.New("injected exhange rate votes and generated exchange votes are not equal") + } + } + + return nil +} diff --git a/x/oracle/abci/voteextension.go b/x/oracle/abci/voteextension.go index 85d59398..1c7f16e7 100644 --- a/x/oracle/abci/voteextension.go +++ b/x/oracle/abci/voteextension.go @@ -16,12 +16,11 @@ import ( // OracleVoteExtension defines the canonical vote extension structure. type OracleVoteExtension struct { - Height int64 - ExchangeRates sdk.DecCoins - ValidatorAddress sdk.ValAddress + Height int64 + ExchangeRates sdk.DecCoins } -type VoteExtHandler struct { +type VoteExtensionHandler struct { logger log.Logger oracleKeeper keeper.Keeper priceFeeder *pricefeeder.PriceFeeder @@ -32,15 +31,15 @@ func NewVoteExtensionHandler( logger log.Logger, oracleKeeper keeper.Keeper, priceFeeder *pricefeeder.PriceFeeder, -) *VoteExtHandler { - return &VoteExtHandler{ +) *VoteExtensionHandler { + return &VoteExtensionHandler{ logger: logger, oracleKeeper: oracleKeeper, priceFeeder: priceFeeder, } } -func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { +func (h *VoteExtensionHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return func(ctx sdk.Context, req *cometabci.RequestExtendVote) (resp *cometabci.ResponseExtendVote, err error) { defer func() { // catch panics if possible @@ -91,9 +90,8 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { } voteExt := OracleVoteExtension{ - Height: req.Height, - ExchangeRates: filteredDecCoins, - ValidatorAddress: *h.priceFeeder.ValidatorAddress, + Height: req.Height, + ExchangeRates: filteredDecCoins, } bz, err := json.Marshal(voteExt) @@ -114,7 +112,7 @@ func (h *VoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { } } -func (h *VoteExtHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { +func (h *VoteExtensionHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { return func(ctx sdk.Context, req *cometabci.RequestVerifyVoteExtension) ( *cometabci.ResponseVerifyVoteExtension, error, diff --git a/x/oracle/abci/voteextension_test.go b/x/oracle/abci/voteextension_test.go index ed03ec94..76494ed9 100644 --- a/x/oracle/abci/voteextension_test.go +++ b/x/oracle/abci/voteextension_test.go @@ -1,7 +1,61 @@ package abci_test +import ( + "cosmossdk.io/log" + cometabci "github.com/cometbft/cometbft/abci/types" + + "github.com/ojo-network/ojo/pricefeeder" + "github.com/ojo-network/ojo/x/oracle/abci" + "github.com/ojo-network/ojo/x/oracle/keeper" +) + func (s *IntegrationTestSuite) TestExtendVoteHandler() { + app, ctx := s.app, s.ctx + + testCases := []struct { + name string + logger log.Logger + oracleKeeper keeper.Keeper + priceFeeder *pricefeeder.PriceFeeder + extendVoteRequest func() *cometabci.RequestExtendVote + expErr bool + expErrMsg string + }{ + { + name: "nil price feeder", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + priceFeeder: app.PriceFeeder, + expErr: true, + expErrMsg: "price feeder oracle not set", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + h := abci.NewVoteExtensionHandler( + tc.logger, + tc.oracleKeeper, + tc.priceFeeder, + ) + req := &cometabci.RequestExtendVote{} + if tc.extendVoteRequest != nil { + req = tc.extendVoteRequest() + } + resp, err := h.ExtendVoteHandler()(ctx, req) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + if resp == nil || len(resp.VoteExtension) == 0 { + return + } + s.Require().NoError(err) + s.Require().NotNil(resp) + } + }) + } } func (s *IntegrationTestSuite) TestVerifyVoteExtensionHandler() { From d09cbd6d28f2dd91011d4223a872b725dc5b9b16 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 26 Mar 2024 20:55:58 -0400 Subject: [PATCH 09/27] add vote extention and preblocker integration tests --- app/upgrades.go | 2 +- x/oracle/abci/abci_test.go | 79 ++++++------------ x/oracle/abci/preblocker_test.go | 78 ++++++++++++++++++ x/oracle/abci/voteextension_test.go | 120 +++++++++++++++++++++++++--- 4 files changed, 213 insertions(+), 66 deletions(-) diff --git a/app/upgrades.go b/app/upgrades.go index b36fe739..9200c227 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -57,7 +57,7 @@ func (app *App) registerUpgrade0_1_4(_ upgradetypes.Plan) { ) } -//nolint: all +// nolint: all func (app *App) registerUpgrade0_2_0(upgradeInfo upgradetypes.Plan) { const planName = "v0.2.0" diff --git a/x/oracle/abci/abci_test.go b/x/oracle/abci/abci_test.go index 05d85222..a130f107 100644 --- a/x/oracle/abci/abci_test.go +++ b/x/oracle/abci/abci_test.go @@ -1,22 +1,21 @@ package abci_test import ( - // "context" "testing" - // "time" + "time" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ojo-network/ojo/tests/integration" - // "github.com/rs/zerolog" + "github.com/rs/zerolog" "github.com/stretchr/testify/suite" ojoapp "github.com/ojo-network/ojo/app" - // "github.com/ojo-network/ojo/pricefeeder" - // "github.com/ojo-network/price-feeder/oracle" - // "github.com/ojo-network/price-feeder/oracle/client" - // "github.com/ojo-network/price-feeder/oracle/provider" - // "github.com/ojo-network/price-feeder/oracle/types" + "github.com/ojo-network/ojo/pricefeeder" + "github.com/ojo-network/price-feeder/oracle" + "github.com/ojo-network/price-feeder/oracle/client" + "github.com/ojo-network/price-feeder/oracle/provider" + "github.com/ojo-network/price-feeder/oracle/types" ) type IntegrationTestSuite struct { @@ -36,48 +35,22 @@ func TestAbciTestSuite(t *testing.T) { suite.Run(t, new(IntegrationTestSuite)) } -// func MockPriceFeeder(ctx context.Context) *pricefeeder.PriceFeeder { -// providers := make(map[types.ProviderName][]types.CurrencyPair) -// deviations := make(map[string]math.LegacyDec) -// providerEndpointsMap := make(map[types.ProviderName]provider.Endpoint) - -// oracle := oracle.New( -// zerolog.Nop(), -// client.OracleClient{}, -// providers, -// time.Second*10, -// deviations, -// providerEndpointsMap, -// false, -// ) - -// oracle.SetPrices(ctx) - -// return &pricefeeder.PriceFeeder{ -// Oracle: oracle, -// } -// } - -// type MockProvider struct {} - -// func (mp *MockProvider) GetTickerPrices(pairs ...types.CurrencyPair) (types.CurrencyPairTickers, error) { -// tickerPrices := make(types.CurrencyPairTickers, len(pairs)) - -// } - -// func (mp *MockProvider) GetCandlePrices(pairs ...types.CurrencyPair) (types.CurrencyPairCandles, error) { - -// } - -// func NewMockProvider() MockProvider { -// ojoPair := types.CurrencyPair{ -// Base: "OJO", -// Quote: "USD", -// Address: "OJOADDRESS", -// } -// usdcPair := types.CurrencyPair{ -// Base: "USDC", -// Quote: "USD", -// Address: "USDCADDRESS", -// } -// } +func MockPriceFeeder() *pricefeeder.PriceFeeder { + providers := make(map[types.ProviderName][]types.CurrencyPair) + deviations := make(map[string]math.LegacyDec) + providerEndpointsMap := make(map[types.ProviderName]provider.Endpoint) + + oracle := oracle.New( + zerolog.Nop(), + client.OracleClient{}, + providers, + time.Second*10, + deviations, + providerEndpointsMap, + false, + ) + + return &pricefeeder.PriceFeeder{ + Oracle: oracle, + } +} diff --git a/x/oracle/abci/preblocker_test.go b/x/oracle/abci/preblocker_test.go index 7892e62e..dc8d402d 100644 --- a/x/oracle/abci/preblocker_test.go +++ b/x/oracle/abci/preblocker_test.go @@ -1,5 +1,83 @@ package abci_test +import ( + "encoding/json" + + "cosmossdk.io/log" + "cosmossdk.io/math" + cometabci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/ojo-network/ojo/x/oracle/abci" + "github.com/ojo-network/ojo/x/oracle/keeper" + oracletypes "github.com/ojo-network/ojo/x/oracle/types" +) + func (s *IntegrationTestSuite) TestPreBlocker() { + app, ctx, keys := s.app, s.ctx, s.keys + voter := keys[0].ValAddress + + // build injected vote extention tx + injectedVoteExtTx := abci.AggregateExchangeRateVotes{ + ExchangeRateVotes: []oracletypes.AggregateExchangeRateVote{ + { + ExchangeRates: sdk.NewDecCoinsFromCoins(sdk.NewCoin("ATOM", math.NewInt(11))), + Voter: voter.String(), + }, + }, + } + bz, err := json.Marshal(injectedVoteExtTx) + s.Require().NoError(err) + var txs [][]byte + txs = append(txs, bz) + + testCases := []struct { + name string + logger log.Logger + oracleKeeper keeper.Keeper + finalizeBlockRequest *cometabci.RequestFinalizeBlock + expErr bool + expErrMsg string + }{ + { + name: "nil preblocker request", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + expErr: true, + expErrMsg: "preblocker received a nil request", + }, + { + name: "oracle preblocker sets exchange rate", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + finalizeBlockRequest: &cometabci.RequestFinalizeBlock{ + Height: ctx.BlockHeight(), + Txs: txs, + }, + expErr: false, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + h := abci.NewPreBlockHandler( + tc.logger, + tc.oracleKeeper, + ) + + resp, err := h.PreBlocker()(ctx, tc.finalizeBlockRequest) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + s.Require().NoError(err) + s.Require().NotNil(resp) + // check exchange rate vote was set + // exchangeRateVotes, err := tc.oracleKeeper.GetAggregateExchangeRateVote(ctx, voter) + // s.Require().NoError(err) + // fmt.Println("exchangeRateVotes", exchangeRateVotes) + } + }) + } } diff --git a/x/oracle/abci/voteextension_test.go b/x/oracle/abci/voteextension_test.go index 76494ed9..5271b55f 100644 --- a/x/oracle/abci/voteextension_test.go +++ b/x/oracle/abci/voteextension_test.go @@ -1,6 +1,9 @@ package abci_test import ( + "encoding/json" + "fmt" + "cosmossdk.io/log" cometabci "github.com/cometbft/cometbft/abci/types" @@ -11,23 +14,45 @@ import ( func (s *IntegrationTestSuite) TestExtendVoteHandler() { app, ctx := s.app, s.ctx + pf := MockPriceFeeder() testCases := []struct { name string logger log.Logger oracleKeeper keeper.Keeper priceFeeder *pricefeeder.PriceFeeder - extendVoteRequest func() *cometabci.RequestExtendVote + extendVoteRequest *cometabci.RequestExtendVote expErr bool expErrMsg string }{ { - name: "nil price feeder", + name: "nil vote extension request", logger: log.NewNopLogger(), oracleKeeper: app.OracleKeeper, - priceFeeder: app.PriceFeeder, + priceFeeder: pf, expErr: true, - expErrMsg: "price feeder oracle not set", + expErrMsg: "extend vote handler received a nil request", + }, + { + name: "price feeder oracle not set", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + priceFeeder: app.PriceFeeder, + extendVoteRequest: &cometabci.RequestExtendVote{ + Height: ctx.BlockHeight(), + }, + expErr: true, + expErrMsg: "price feeder oracle not set", + }, + { + name: "vote extension handled successfully", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + priceFeeder: pf, + extendVoteRequest: &cometabci.RequestExtendVote{ + Height: ctx.BlockHeight(), + }, + expErr: false, }, } @@ -39,25 +64,96 @@ func (s *IntegrationTestSuite) TestExtendVoteHandler() { tc.priceFeeder, ) - req := &cometabci.RequestExtendVote{} - if tc.extendVoteRequest != nil { - req = tc.extendVoteRequest() - } - resp, err := h.ExtendVoteHandler()(ctx, req) + resp, err := h.ExtendVoteHandler()(ctx, tc.extendVoteRequest) if tc.expErr { s.Require().Error(err) s.Require().Contains(err.Error(), tc.expErrMsg) } else { - if resp == nil || len(resp.VoteExtension) == 0 { - return - } s.Require().NoError(err) s.Require().NotNil(resp) + s.Require().Greater(len(resp.VoteExtension), 0) + + var voteExt abci.OracleVoteExtension + err = json.Unmarshal(resp.VoteExtension, &voteExt) + s.Require().NoError(err) + s.Require().Equal(ctx.BlockHeight(), voteExt.Height) } }) } } func (s *IntegrationTestSuite) TestVerifyVoteExtensionHandler() { + app, ctx := s.app, s.ctx + pf := MockPriceFeeder() + + voteExtension, err := json.Marshal(&cometabci.RequestExtendVote{ + Height: ctx.BlockHeight(), + }) + s.Require().NoError(err) + + testCases := []struct { + name string + logger log.Logger + oracleKeeper keeper.Keeper + priceFeeder *pricefeeder.PriceFeeder + verifyVoteRequest *cometabci.RequestVerifyVoteExtension + expErr bool + expErrMsg string + }{ + { + name: "nil verify vote extension request", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + priceFeeder: pf, + expErr: true, + expErrMsg: "verify vote extension handler received a nil request", + }, + { + name: "vote extension and verify vote extension height mismatch", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + priceFeeder: pf, + verifyVoteRequest: &cometabci.RequestVerifyVoteExtension{ + Height: ctx.BlockHeight() + 1, + VoteExtension: voteExtension, + }, + expErr: true, + expErrMsg: fmt.Sprintf("verify vote extension handler received vote extension height that doesn't"+ + "match request height; expected: %d, got: %d", + ctx.BlockHeight()+1, + ctx.BlockHeight(), + ), + }, + { + name: "vote extension verified successfully", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + priceFeeder: pf, + verifyVoteRequest: &cometabci.RequestVerifyVoteExtension{ + Height: ctx.BlockHeight(), + VoteExtension: voteExtension, + }, + expErr: false, + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + h := abci.NewVoteExtensionHandler( + tc.logger, + tc.oracleKeeper, + tc.priceFeeder, + ) + resp, err := h.VerifyVoteExtensionHandler()(ctx, tc.verifyVoteRequest) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + s.Require().NoError(err) + s.Require().NotNil(resp) + s.Require().Equal(cometabci.ResponseVerifyVoteExtension_ACCEPT, resp.Status) + } + }) + } } From 9e234a0dd743794f0bf72a8a589febfd0a7a9bbb Mon Sep 17 00:00:00 2001 From: rbajollari Date: Wed, 27 Mar 2024 11:13:51 -0400 Subject: [PATCH 10/27] fix preblocker test --- x/oracle/abci/preblocker_test.go | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/x/oracle/abci/preblocker_test.go b/x/oracle/abci/preblocker_test.go index dc8d402d..141ccd34 100644 --- a/x/oracle/abci/preblocker_test.go +++ b/x/oracle/abci/preblocker_test.go @@ -6,6 +6,7 @@ import ( "cosmossdk.io/log" "cosmossdk.io/math" cometabci "github.com/cometbft/cometbft/abci/types" + cometprototypes "github.com/cometbft/cometbft/proto/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ojo-network/ojo/x/oracle/abci" @@ -17,13 +18,22 @@ func (s *IntegrationTestSuite) TestPreBlocker() { app, ctx, keys := s.app, s.ctx, s.keys voter := keys[0].ValAddress + // enable vote extensions + ctx = ctx.WithBlockHeight(3) + consensusParams := ctx.ConsensusParams() + consensusParams.Abci = &cometprototypes.ABCIParams{ + VoteExtensionsEnableHeight: 2, + } + ctx = ctx.WithConsensusParams(consensusParams) + // build injected vote extention tx + exchangeRateVoteAtom := oracletypes.AggregateExchangeRateVote{ + ExchangeRates: sdk.NewDecCoinsFromCoins(sdk.NewCoin("ATOM", math.NewInt(11))), + Voter: voter.String(), + } injectedVoteExtTx := abci.AggregateExchangeRateVotes{ ExchangeRateVotes: []oracletypes.AggregateExchangeRateVote{ - { - ExchangeRates: sdk.NewDecCoinsFromCoins(sdk.NewCoin("ATOM", math.NewInt(11))), - Voter: voter.String(), - }, + exchangeRateVoteAtom, }, } bz, err := json.Marshal(injectedVoteExtTx) @@ -74,9 +84,9 @@ func (s *IntegrationTestSuite) TestPreBlocker() { s.Require().NotNil(resp) // check exchange rate vote was set - // exchangeRateVotes, err := tc.oracleKeeper.GetAggregateExchangeRateVote(ctx, voter) - // s.Require().NoError(err) - // fmt.Println("exchangeRateVotes", exchangeRateVotes) + exchangeRateVote, err := tc.oracleKeeper.GetAggregateExchangeRateVote(ctx, voter) + s.Require().NoError(err) + s.Require().Equal(exchangeRateVoteAtom, exchangeRateVote) } }) } From 69ea14f6a4d3c8c62a680fc0150dd4b2557049f0 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Wed, 27 Mar 2024 11:14:48 -0400 Subject: [PATCH 11/27] nolint spacing revert --- app/upgrades.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/upgrades.go b/app/upgrades.go index 9200c227..b36fe739 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -57,7 +57,7 @@ func (app *App) registerUpgrade0_1_4(_ upgradetypes.Plan) { ) } -// nolint: all +//nolint: all func (app *App) registerUpgrade0_2_0(upgradeInfo upgradetypes.Plan) { const planName = "v0.2.0" From b96a12bca398000ea73a240f6c8fa77eb847c9ef Mon Sep 17 00:00:00 2001 From: rbajollari Date: Thu, 28 Mar 2024 18:31:37 -0400 Subject: [PATCH 12/27] go mod tidy --- go.mod | 3 +++ go.sum | 3 +++ 2 files changed, 6 insertions(+) diff --git a/go.mod b/go.mod index 5a2ceb4c..f6255494 100644 --- a/go.mod +++ b/go.mod @@ -158,6 +158,7 @@ require ( github.com/fzipp/gocyclo v0.6.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect + github.com/ghodss/yaml v1.0.0 // indirect github.com/ghostiam/protogetter v0.2.3 // indirect github.com/go-chi/chi/v5 v5.0.8 // indirect github.com/go-critic/go-critic v0.9.0 // indirect @@ -247,6 +248,7 @@ require ( github.com/kisielk/gotool v1.0.0 // indirect github.com/kkHAIKE/contextcheck v1.1.4 // indirect github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect github.com/kulti/thelper v0.6.3 // indirect @@ -364,6 +366,7 @@ require ( go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect go.opentelemetry.io/otel v1.22.0 // indirect go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.22.0 // indirect go.tmz.dev/musttag v0.7.2 // indirect go.uber.org/atomic v1.10.0 // indirect diff --git a/go.sum b/go.sum index 47d023be..b15a7c3f 100644 --- a/go.sum +++ b/go.sum @@ -555,6 +555,7 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghostiam/protogetter v0.2.3 h1:qdv2pzo3BpLqezwqfGDLZ+nHEYmc5bUpIdsMbBVwMjw= github.com/ghostiam/protogetter v0.2.3/go.mod h1:KmNLOsy1v04hKbvZs8EfGI1fk39AgTdRDxWNYPfXVc4= @@ -958,6 +959,8 @@ github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= From 501537c6c0141a0ecfc522c56432335ab4679ad0 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 2 Apr 2024 14:40:42 -0400 Subject: [PATCH 13/27] add abci propsal tests --- tests/integration/test_helpers.go | 5 +- x/oracle/abci/proposal_test.go | 350 ++++++++++++++++++++++++++++++ 2 files changed, 354 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_helpers.go b/tests/integration/test_helpers.go index 89998119..c5c9cef9 100644 --- a/tests/integration/test_helpers.go +++ b/tests/integration/test_helpers.go @@ -28,6 +28,7 @@ const ( var validatorPowers = []int64{599, 398, 2} type TestValidatorKey struct { + PrivKey secp256k1.PrivKey PubKey cryptotypes.PubKey ValAddress sdk.ValAddress AccAddress sdk.AccAddress @@ -38,8 +39,10 @@ func CreateTestValidatorKeys(numValidators int) []TestValidatorKey { var validatorKeys []TestValidatorKey for i := 0; i < numValidators; i++ { - pubKey := secp256k1.GenPrivKey().PubKey() + privKey := secp256k1.GenPrivKey() + pubKey := privKey.PubKey() valInfo := TestValidatorKey{ + PrivKey: *privKey, PubKey: pubKey, ValAddress: sdk.ValAddress(pubKey.Address()), AccAddress: sdk.AccAddress(pubKey.Address()), diff --git a/x/oracle/abci/proposal_test.go b/x/oracle/abci/proposal_test.go index 44e7f9a2..04daad37 100644 --- a/x/oracle/abci/proposal_test.go +++ b/x/oracle/abci/proposal_test.go @@ -1,9 +1,359 @@ package abci_test +import ( + "bytes" + "encoding/json" + "sort" + + "cosmossdk.io/core/header" + "cosmossdk.io/log" + "cosmossdk.io/math" + cometabci "github.com/cometbft/cometbft/abci/types" + cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + protoio "github.com/cosmos/gogoproto/io" + "github.com/cosmos/gogoproto/proto" + "github.com/ojo-network/ojo/tests/integration" + + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + "github.com/ojo-network/ojo/x/oracle/abci" + oraclekeeper "github.com/ojo-network/ojo/x/oracle/keeper" + oracletypes "github.com/ojo-network/ojo/x/oracle/types" +) + func (s *IntegrationTestSuite) TestPrepareProposalHandler() { + app, ctx, keys := s.app, s.ctx, s.keys + + // enable vote extensions + ctx = ctx.WithBlockHeight(3) + consensusParams := ctx.ConsensusParams() + consensusParams.Abci = &cmtproto.ABCIParams{ + VoteExtensionsEnableHeight: 2, + } + ctx = ctx.WithConsensusParams(consensusParams) + + // build local commit info + exchangeRates := sdk.NewDecCoinsFromCoins(sdk.NewCoin("ATOM", math.NewInt(11))) + valKeys := [2]integration.TestValidatorKey{keys[0], keys[1]} + localCommitInfo, err := buildLocalCommitInfo( + ctx, + exchangeRates, + valKeys, + app.ChainID(), + ) + s.Require().NoError(err) + + // update block header info and commit info + ctx = buildCtxHeaderAndCommitInfo(ctx, localCommitInfo, app.ChainID()) + + testCases := []struct { + name string + logger log.Logger + oracleKeeper oraclekeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + prepareProposalRequest *cometabci.RequestPrepareProposal + expErr bool + expErrMsg string + }{ + { + name: "nil prepare proposal request", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + expErr: true, + expErrMsg: "prepare proposal received a nil request", + }, + { + name: "prepare proposal request with nil Txs", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + prepareProposalRequest: &cometabci.RequestPrepareProposal{ + Height: ctx.BlockHeight(), + LocalLastCommit: localCommitInfo, + }, + expErr: true, + expErrMsg: "prepare proposal received a request with nil Txs", + }, + { + name: "prepare proposal request successful", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + prepareProposalRequest: &cometabci.RequestPrepareProposal{ + Height: ctx.BlockHeight(), + Txs: [][]byte{}, + LocalLastCommit: localCommitInfo, + }, + expErr: false, + }, + } + for _, tc := range testCases { + s.Run(tc.name, func() { + h := abci.NewProposalHandler( + tc.logger, + tc.oracleKeeper, + tc.stakingKeeper, + ) + + resp, err := h.PrepareProposalHandler()(ctx, tc.prepareProposalRequest) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + s.Require().NoError(err) + s.Require().NotNil(resp) + + var injectedVoteExtTx abci.AggregateExchangeRateVotes + err = json.Unmarshal(resp.Txs[0], &injectedVoteExtTx) + s.Require().NoError(err) + + sort.Slice(valKeys[:], func(i, j int) bool { + return valKeys[i].ValAddress.String() < valKeys[j].ValAddress.String() + }) + s.Require().Equal(exchangeRates, injectedVoteExtTx.ExchangeRateVotes[0].ExchangeRates) + s.Require().Equal(valKeys[0].ValAddress.String(), injectedVoteExtTx.ExchangeRateVotes[0].Voter) + s.Require().Equal(exchangeRates, injectedVoteExtTx.ExchangeRateVotes[1].ExchangeRates) + s.Require().Equal(valKeys[1].ValAddress.String(), injectedVoteExtTx.ExchangeRateVotes[1].Voter) + } + }) + } } func (s *IntegrationTestSuite) TestProcessProposalHandler() { + app, ctx, keys := s.app, s.ctx, s.keys + + // enable vote extensions + ctx = ctx.WithBlockHeight(3) + consensusParams := ctx.ConsensusParams() + consensusParams.Abci = &cmtproto.ABCIParams{ + VoteExtensionsEnableHeight: 2, + } + ctx = ctx.WithConsensusParams(consensusParams) + + // build local commit info + exchangeRates := sdk.NewDecCoinsFromCoins(sdk.NewCoin("ATOM", math.NewInt(11))) + valKeys := [2]integration.TestValidatorKey{keys[0], keys[1]} + localCommitInfo, err := buildLocalCommitInfo( + ctx, + exchangeRates, + valKeys, + app.ChainID(), + ) + s.Require().NoError(err) + + // build local commit info with different exchange rate + exchangeRatesConflicting := sdk.NewDecCoinsFromCoins(sdk.NewCoin("ATOM", math.NewInt(111))) + localCommitInfoConflicting, err := buildLocalCommitInfo( + ctx, + exchangeRatesConflicting, + valKeys, + app.ChainID(), + ) + s.Require().NoError(err) + + // build injected vote extention tx + sort.Slice(valKeys[:], func(i, j int) bool { + return valKeys[i].ValAddress.String() < valKeys[j].ValAddress.String() + }) + exchangeRateVotes := []oracletypes.AggregateExchangeRateVote{ + { + ExchangeRates: exchangeRates, + Voter: valKeys[0].ValAddress.String(), + }, + { + ExchangeRates: exchangeRates, + Voter: valKeys[1].ValAddress.String(), + }, + } + injectedVoteExtTx := abci.AggregateExchangeRateVotes{ + ExchangeRateVotes: exchangeRateVotes, + ExtendedCommitInfo: localCommitInfo, + } + bz, err := json.Marshal(injectedVoteExtTx) + s.Require().NoError(err) + var txs [][]byte + txs = append(txs, bz) + + // create tx with conflicting local commit info + injectedVoteExtTxConflicting := abci.AggregateExchangeRateVotes{ + ExchangeRateVotes: exchangeRateVotes, + ExtendedCommitInfo: localCommitInfoConflicting, + } + bz, err = json.Marshal(injectedVoteExtTxConflicting) + s.Require().NoError(err) + var txsConflicting [][]byte + txsConflicting = append(txsConflicting, bz) + + // update block header info and commit info + ctx = buildCtxHeaderAndCommitInfo(ctx, localCommitInfo, app.ChainID()) + + testCases := []struct { + name string + logger log.Logger + oracleKeeper oraclekeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + processProposalRequest *cometabci.RequestProcessProposal + expErr bool + expErrMsg string + }{ + { + name: "nil process proposal request", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + expErr: true, + expErrMsg: "process proposal received a nil request", + }, + { + name: "process proposal request with nil Txs", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + processProposalRequest: &cometabci.RequestProcessProposal{ + Height: ctx.BlockHeight(), + }, + expErr: true, + expErrMsg: "process proposal received a request with nil Txs", + }, + { + name: "process proposal request successful", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + processProposalRequest: &cometabci.RequestProcessProposal{ + Height: ctx.BlockHeight(), + Txs: txs, + }, + expErr: false, + }, + { + name: "process proposal request fails to verify exchange rate votes", + logger: log.NewNopLogger(), + oracleKeeper: app.OracleKeeper, + stakingKeeper: app.StakingKeeper, + processProposalRequest: &cometabci.RequestProcessProposal{ + Height: ctx.BlockHeight(), + Txs: txsConflicting, + }, + expErr: true, + expErrMsg: "injected exhange rate votes and generated exchange votes are not equal", + }, + } + + for _, tc := range testCases { + s.Run(tc.name, func() { + h := abci.NewProposalHandler( + tc.logger, + tc.oracleKeeper, + tc.stakingKeeper, + ) + + resp, err := h.ProcessProposalHandler()(ctx, tc.processProposalRequest) + if tc.expErr { + s.Require().Error(err) + s.Require().Contains(err.Error(), tc.expErrMsg) + } else { + s.Require().NoError(err) + s.Require().NotNil(resp) + s.Require().Equal(cometabci.ResponseProcessProposal_ACCEPT, resp.Status) + } + }) + } +} + +func buildCtxHeaderAndCommitInfo( + ctx sdk.Context, + localCommitInfo cometabci.ExtendedCommitInfo, + chainID string, +) sdk.Context { + headerInfo := header.Info{ + Height: ctx.BlockHeight(), + Time: ctx.BlockTime(), + ChainID: chainID, + } + ctx = ctx.WithHeaderInfo(headerInfo) + misbehavior := make([]cometabci.Misbehavior, 0) + validatorHash := make([]byte, 0) + proposerAddress := make([]byte, 0) + lastCommit := cometabci.CommitInfo{ + Round: 0, + Votes: []cometabci.VoteInfo{ + { + Validator: localCommitInfo.Votes[0].Validator, + BlockIdFlag: cmtproto.BlockIDFlagCommit, + }, + { + Validator: localCommitInfo.Votes[1].Validator, + BlockIdFlag: cmtproto.BlockIDFlagCommit, + }, + }, + } + + return ctx.WithCometInfo(baseapp.NewBlockInfo(misbehavior, validatorHash, proposerAddress, lastCommit)) +} + +// Builds local commit info with exchange rates and 2 validators +func buildLocalCommitInfo( + ctx sdk.Context, + exchangeRates sdk.DecCoins, + valKeys [2]integration.TestValidatorKey, + chainID string, +) (cometabci.ExtendedCommitInfo, error) { + voteExt := abci.OracleVoteExtension{ + ExchangeRates: exchangeRates, + Height: ctx.BlockHeight(), + } + bz, err := json.Marshal(voteExt) + if err != nil { + return cometabci.ExtendedCommitInfo{}, err + } + + marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { + var buf bytes.Buffer + if err := protoio.NewDelimitedWriter(&buf).WriteMsg(msg); err != nil { + return nil, err + } + + return buf.Bytes(), nil + } + cve := cmtproto.CanonicalVoteExtension{ + Extension: bz, + Height: ctx.BlockHeight() - 1, // the vote extension was signed in the previous height + Round: 0, + ChainId: chainID, + } + extSignBytes, err := marshalDelimitedFn(&cve) + if err != nil { + return cometabci.ExtendedCommitInfo{}, err + } + + votes := make([]cometabci.ExtendedVoteInfo, 2) + for i := range votes { + valConsAddr := sdk.ConsAddress(valKeys[i].PubKey.Address()) + extSig, err := valKeys[i].PrivKey.Sign(extSignBytes) + if err != nil { + return cometabci.ExtendedCommitInfo{}, err + } + + votes[i] = cometabci.ExtendedVoteInfo{ + Validator: cometabci.Validator{ + Address: valConsAddr, + Power: 100, + }, + VoteExtension: bz, + BlockIdFlag: cmtproto.BlockIDFlagCommit, + ExtensionSignature: extSig, + } + } + sort.Slice(votes, func(i, j int) bool { + return string(votes[i].Validator.Address) < string(votes[j].Validator.Address) + }) + return cometabci.ExtendedCommitInfo{ + Round: 0, + Votes: votes, + }, nil } From 336f5a57f11c1969e26da69369d58277ad106b89 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Wed, 3 Apr 2024 11:46:48 -0400 Subject: [PATCH 14/27] update price feeder import --- go.mod | 2 +- go.sum | 7 +++---- pricefeeder/price-feeder.example.toml | 9 +-------- pricefeeder/pricefeeder.go | 1 - x/oracle/types/params.go | 11 +++++++++++ 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index f6255494..63ec3e41 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 github.com/mgechev/revive v1.3.6 github.com/mitchellh/mapstructure v1.5.0 - github.com/ojo-network/price-feeder v0.1.10-0.20240221234245-b3d7d675adc9 + github.com/ojo-network/price-feeder v0.1.11-0.20240403153904-aeda5a5840a6 github.com/ory/dockertest/v3 v3.10.0 github.com/rs/zerolog v1.32.0 github.com/spf13/cast v1.6.0 diff --git a/go.sum b/go.sum index b15a7c3f..7bb9f454 100644 --- a/go.sum +++ b/go.sum @@ -636,9 +636,8 @@ github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk= -github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= @@ -1093,8 +1092,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= -github.com/ojo-network/price-feeder v0.1.10-0.20240221234245-b3d7d675adc9 h1:FcfDjXO3s6iOovc6qtgb7EWcrj68gQwAfwrI/AOd/ik= -github.com/ojo-network/price-feeder v0.1.10-0.20240221234245-b3d7d675adc9/go.mod h1:mZfH9RJMBaRAAvR6Rll59HHTz02gde1ebS/EexjOT8M= +github.com/ojo-network/price-feeder v0.1.11-0.20240403153904-aeda5a5840a6 h1:2txECFIt4gxKj1ryBbmjv3H5FVgXByZUr+vcm9hbh5g= +github.com/ojo-network/price-feeder v0.1.11-0.20240403153904-aeda5a5840a6/go.mod h1:2xHrCcUMPoozsvst9785vToD7/U05OOAAl0NvnMYaTg= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= diff --git a/pricefeeder/price-feeder.example.toml b/pricefeeder/price-feeder.example.toml index af454e94..6b2607a3 100644 --- a/pricefeeder/price-feeder.example.toml +++ b/pricefeeder/price-feeder.example.toml @@ -306,13 +306,6 @@ providers = [ ] quote = "USD" -[[currency_pairs]] -base = "STINJ" -providers = [ - "astroport", -] -quote = "INJ" - [server] listen_addr = "0.0.0.0:7171" read_timeout = "20s" @@ -329,6 +322,6 @@ enable-hostname = true enable-hostname-label = true enable-service-label = true enabled = true -global-labels = [["chain_id", "ojotest-1"]] +global-labels = [["chain_id", "ojo-testnet"]] service-name = "price-feeder" prometheus-retention-time = 100 diff --git a/pricefeeder/pricefeeder.go b/pricefeeder/pricefeeder.go index 3e059241..51f7f07a 100644 --- a/pricefeeder/pricefeeder.go +++ b/pricefeeder/pricefeeder.go @@ -30,7 +30,6 @@ const ( envConfig = "PRICE_FEEDER_CONFIG" envChainConfig = "PRICE_FEEDER_CHAIN_CONFIG" envDebugLevel = "PRICE_FEEDER_LOG_LEVEL" - envVariablePass = "PRICE_FEEDER_PASS" envOracleTickTime = "PRICE_FEEDER_ORACLE_TICK_TIME" ) diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 4d6a69ee..de7c20b9 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -83,6 +83,13 @@ var ( "coinbase", }, }, + CurrencyPairProviders{ + BaseDenom: AtomSymbol, + QuoteDenom: USDDenom, + Providers: []string{ + "kraken", + }, + }, } DefaultCurrencyDeviationThresholds = CurrencyDeviationThresholdList{ @@ -90,6 +97,10 @@ var ( BaseDenom: OjoSymbol, Threshold: "2", }, + CurrencyDeviationThreshold{ + BaseDenom: AtomSymbol, + Threshold: "2", + }, } ) From a8b13ec0bc782521a161f67a33b371ff20dd5ce6 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Thu, 4 Apr 2024 14:15:13 -0400 Subject: [PATCH 15/27] add price feeder app config --- cmd/ojod/cmd/commands.go | 38 ++++++++++++++-- cmd/ojod/cmd/root.go | 6 +-- config.yml | 3 ++ pricefeeder/config.go | 90 ++++++++++++++++++++++++++++++++++++++ pricefeeder/pricefeeder.go | 30 +++---------- scripts/single-node.sh | 5 +-- 6 files changed, 138 insertions(+), 34 deletions(-) create mode 100644 pricefeeder/config.go diff --git a/cmd/ojod/cmd/commands.go b/cmd/ojod/cmd/commands.go index 77fd4c0f..696187a9 100644 --- a/cmd/ojod/cmd/commands.go +++ b/cmd/ojod/cmd/commands.go @@ -4,6 +4,7 @@ import ( "errors" "io" "os" + "time" "cosmossdk.io/log" "cosmossdk.io/tools/confix/cmd" @@ -30,6 +31,7 @@ import ( "github.com/spf13/cobra" app "github.com/ojo-network/ojo/app" + "github.com/ojo-network/ojo/pricefeeder" oracletypes "github.com/ojo-network/ojo/x/oracle/types" ) @@ -54,19 +56,31 @@ func initAppConfig() (string, interface{}) { type CustomAppConfig struct { serverconfig.Config - WASM WASMConfig `mapstructure:"wasm"` + WASM WASMConfig `mapstructure:"wasm"` + PriceFeeder pricefeeder.AppConfig `mapstructure:"pricefeeder"` } // here we set a default initial app.toml values for validators. srvCfg := serverconfig.DefaultConfig() srvCfg.MinGasPrices = "" // validators MUST set mininum-gas-prices in their app.toml, otherwise the app will halt. + dir, err := os.UserHomeDir() + if err != nil { + panic(err) + } + customAppConfig := CustomAppConfig{ Config: *srvCfg, WASM: WASMConfig{ LruSize: 1, QueryGasLimit: 300000, }, + PriceFeeder: pricefeeder.AppConfig{ + ConfigPath: dir + "/ojo/pricefeeder/price-feeder.example.toml", + ChainConfig: true, + LogLevel: "info", + OracleTickTime: time.Second * 5, + }, } customAppTemplate := serverconfig.DefaultConfigTemplate + ` @@ -75,7 +89,7 @@ func initAppConfig() (string, interface{}) { query_gas_limit = 300000 # This is the number of wasm vm instances we keep cached in memory for speed-up # Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally -lru_size = 0` +lru_size = 0` + pricefeeder.DefaultConfigTemplate return customAppTemplate, customAppConfig } @@ -119,6 +133,20 @@ func initRootCmd( txCommand(), keys.Commands(), ) + + // add price feeder flags + rootCmd.PersistentFlags().String(pricefeeder.FlagConfigPath, "", "Path to price feeder config file") + rootCmd.PersistentFlags().Bool( + pricefeeder.FlagChainConfig, + true, + "Specifies whether the currency pair providers and currency deviation threshold values should", + ) + rootCmd.PersistentFlags().String(pricefeeder.FlagLogLevel, "", "Log level of price feeder process") + rootCmd.PersistentFlags().Duration( + pricefeeder.FlagOracleTickTime, + time.Second*5, + "Time interval that the price feeder's oracle process waits before fetching for new prices", + ) } // genesisCommand builds genesis-related `simd genesis` command. Users may @@ -204,10 +232,14 @@ func newApp( ) // start price feeder + appConfig, err := pricefeeder.ReadConfigFromAppOpts(appOpts) + if err != nil { + panic(err) + } var oracleGenState oracletypes.GenesisState app.AppCodec().MustUnmarshalJSON(app.DefaultGenesis()[oracletypes.ModuleName], &oracleGenState) go func() { - err := app.PriceFeeder.Start(oracleGenState.Params) + err := app.PriceFeeder.Start(oracleGenState.Params, appConfig) if err != nil { panic(err) } diff --git a/cmd/ojod/cmd/root.go b/cmd/ojod/cmd/root.go index a844a9ee..c03c4846 100644 --- a/cmd/ojod/cmd/root.go +++ b/cmd/ojod/cmd/root.go @@ -52,9 +52,9 @@ func NewRootCmd() *cobra.Command { rootCmd := &cobra.Command{ Use: appparams.Name + "d", Short: "Ojo application network daemon and client", - Long: `A daemon and client for interacting with the Ojo network. Ojo is a -Universal Capital Facility that can collateralize assets on one blockchain -towards borrowing assets on another blockchain.`, + Long: `A daemon and client for interacting with the Ojo network. Ojo is an +oracle platform which other blockchains and smart contracts can use to receive +up-to-date and accurate data.`, PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // set the default command outputs cmd.SetOut(cmd.OutOrStdout()) diff --git a/config.yml b/config.yml index 1f95cfe7..3d6a8c70 100644 --- a/config.yml +++ b/config.yml @@ -41,3 +41,6 @@ genesis: validators: - name: alice bonded: 33500000000000uojo + app: + pricefeeder: + config_path: "PATH TO PRICE FEEDER CONFIG HERE" diff --git a/pricefeeder/config.go b/pricefeeder/config.go new file mode 100644 index 00000000..b02b3783 --- /dev/null +++ b/pricefeeder/config.go @@ -0,0 +1,90 @@ +package pricefeeder + +import ( + "fmt" + "time" + + servertypes "github.com/cosmos/cosmos-sdk/server/types" + "github.com/spf13/cast" +) + +const ( + DefaultConfigTemplate = ` +[pricefeeder] +# Path to price feeder config file +config_path = "" +# Specifies whether the currency pair providers and currency deviation threshold values should +# be read from the oracle module's on chain parameters or the price feeder config +chain_config = true +# Log level of price feeder process +log_level = "info" +# Time interval that the price feeder's oracle process waits before fetching for new prices +oracle_tick_time = "5s" +` +) + +const ( + FlagConfigPath = "pricefeeder.config_path" + FlagChainConfig = "pricefeeder.chain_config" + FlagLogLevel = "pricefeeder.log_level" + FlagOracleTickTime = "pricefeeder.oracle_tick_time" +) + +// AppConfig defines the app configuration for the price feeder that must be set in the app.toml file. +type AppConfig struct { + ConfigPath string `mapstructure:"config_path"` + ChainConfig bool `mapstructure:"chain_config"` + LogLevel string `mapstructure:"log_level"` + OracleTickTime time.Duration `mapstructure:"oracle_tick_time"` +} + +// ValidateBasic performs basic validation of the price feeder app config. +func (c *AppConfig) ValidateBasic() error { + if c.ConfigPath == "" { + return fmt.Errorf("path to price feeder config must be set") + } + + if c.OracleTickTime <= 0 { + return fmt.Errorf("oracle tick time must be greater than 0") + } + + return nil +} + +// ReadConfigFromAppOpts reads the config parameters from the AppOptions and returns the config. +func ReadConfigFromAppOpts(opts servertypes.AppOptions) (AppConfig, error) { + var ( + cfg AppConfig + err error + ) + + if v := opts.Get(FlagConfigPath); v != nil { + if cfg.ConfigPath, err = cast.ToStringE(v); err != nil { + return cfg, err + } + } + + if v := opts.Get(FlagChainConfig); v != nil { + if cfg.ChainConfig, err = cast.ToBoolE(v); err != nil { + return cfg, err + } + } + + if v := opts.Get(FlagLogLevel); v != nil { + if cfg.LogLevel, err = cast.ToStringE(v); err != nil { + return cfg, err + } + } + + if v := opts.Get(FlagOracleTickTime); v != nil { + if cfg.OracleTickTime, err = cast.ToDurationE(v); err != nil { + return cfg, err + } + } + + if err := cfg.ValidateBasic(); err != nil { + return cfg, err + } + + return cfg, err +} diff --git a/pricefeeder/pricefeeder.go b/pricefeeder/pricefeeder.go index 51f7f07a..f87b9d5e 100644 --- a/pricefeeder/pricefeeder.go +++ b/pricefeeder/pricefeeder.go @@ -6,7 +6,6 @@ import ( "net/http" "os" "os/signal" - "strconv" "syscall" "time" @@ -26,26 +25,19 @@ import ( v1 "github.com/ojo-network/price-feeder/router/v1" ) -const ( - envConfig = "PRICE_FEEDER_CONFIG" - envChainConfig = "PRICE_FEEDER_CHAIN_CONFIG" - envDebugLevel = "PRICE_FEEDER_LOG_LEVEL" - envOracleTickTime = "PRICE_FEEDER_ORACLE_TICK_TIME" -) - type PriceFeeder struct { Oracle *oracle.Oracle } -func (pf *PriceFeeder) Start(oracleParams types.Params) error { +func (pf *PriceFeeder) Start(oracleParams types.Params, appConfig AppConfig) error { logWriter := zerolog.ConsoleWriter{Out: os.Stderr} - logLevel, err := zerolog.ParseLevel(os.Getenv(envDebugLevel)) + logLevel, err := zerolog.ParseLevel(appConfig.LogLevel) if err != nil { return err } logger := zerolog.New(logWriter).Level(logLevel).With().Timestamp().Logger() - cfg, err := config.LoadConfigFromFlags(os.Getenv(envConfig), "") + cfg, err := config.LoadConfigFromFlags(appConfig.ConfigPath, "") if err != nil { return err } @@ -67,13 +59,8 @@ func (pf *PriceFeeder) Start(oracleParams types.Params) error { return err } - chainConfig, err := strconv.ParseBool(os.Getenv(envChainConfig)) - if err != nil { - return err - } - // overwite providers and deviations with on chain values if specified - if chainConfig { + if appConfig.ChainConfig { providers = oracle.CreatePairProvidersFromCurrencyPairProvidersList(oracleParams.CurrencyPairProviders) deviations, err = oracle.CreateDeviationsFromCurrencyDeviationThresholdList(oracleParams.CurrencyDeviationThresholds) if err != nil { @@ -88,7 +75,7 @@ func (pf *PriceFeeder) Start(oracleParams types.Params) error { providerTimeout, deviations, cfg.ProviderEndpointsMap(), - chainConfig, + appConfig.ChainConfig, ) telemetryCfg := telemetry.Config{} @@ -101,18 +88,13 @@ func (pf *PriceFeeder) Start(oracleParams types.Params) error { return err } - oracleTickTime, err := time.ParseDuration(os.Getenv(envOracleTickTime)) - if err != nil { - return err - } - g.Go(func() error { // start the process that observes and publishes exchange prices return startPriceFeeder(ctx, logger, cfg, pf.Oracle, metrics) }) g.Go(func() error { // start the process that calculates oracle prices - return startPriceOracle(ctx, logger, pf.Oracle, oracleParams, oracleTickTime) + return startPriceOracle(ctx, logger, pf.Oracle, oracleParams, appConfig.OracleTickTime) }) // Block main process until all spawned goroutines have gracefully exited and diff --git a/scripts/single-node.sh b/scripts/single-node.sh index d089aea9..5095e62b 100755 --- a/scripts/single-node.sh +++ b/scripts/single-node.sh @@ -14,10 +14,6 @@ CWD="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" PRICE_FEEDER_CONFIG_PATH="${CWD}/../pricefeeder/price-feeder.example.toml" -export PRICE_FEEDER_CONFIG=$(realpath "$PRICE_FEEDER_CONFIG_PATH") -export PRICE_FEEDER_CHAIN_CONFIG="FALSE" -export PRICE_FEEDER_LOG_LEVEL="DEBUG" -export PRICE_FEEDER_ORACLE_TICK_TIME="1s" NODE_BIN="${1:-$CWD/../build/ojod}" @@ -161,6 +157,7 @@ if [[ ! -d "$hdir" ]]; then echo "--- Modifying app..." perl -i -pe 's|minimum-gas-prices = ""|minimum-gas-prices = "0.05uojo"|g' $n0app + perl -i -pe 's|config_path = ""|config_path = "'$PRICE_FEEDER_CONFIG_PATH'"|g' $n0app else echo "====================================" From a9584fa19d1f1d8ed9dd73fb92178b0ff7fc8579 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Mon, 8 Apr 2024 10:40:26 -0600 Subject: [PATCH 16/27] fix e2e test setup --- cmd/ojod/cmd/commands.go | 8 +- tests/e2e/e2e_setup_test.go | 19 ++- tests/e2e/e2e_test.go | 19 ++- tests/e2e/orchestrator/orchestrator.go | 157 +++++++------------------ tests/e2e/orchestrator/validator.go | 4 + 5 files changed, 68 insertions(+), 139 deletions(-) diff --git a/cmd/ojod/cmd/commands.go b/cmd/ojod/cmd/commands.go index 696187a9..2478b3c5 100644 --- a/cmd/ojod/cmd/commands.go +++ b/cmd/ojod/cmd/commands.go @@ -64,11 +64,6 @@ func initAppConfig() (string, interface{}) { srvCfg := serverconfig.DefaultConfig() srvCfg.MinGasPrices = "" // validators MUST set mininum-gas-prices in their app.toml, otherwise the app will halt. - dir, err := os.UserHomeDir() - if err != nil { - panic(err) - } - customAppConfig := CustomAppConfig{ Config: *srvCfg, WASM: WASMConfig{ @@ -76,7 +71,7 @@ func initAppConfig() (string, interface{}) { QueryGasLimit: 300000, }, PriceFeeder: pricefeeder.AppConfig{ - ConfigPath: dir + "/ojo/pricefeeder/price-feeder.example.toml", + ConfigPath: "", ChainConfig: true, LogLevel: "info", OracleTickTime: time.Second * 5, @@ -236,6 +231,7 @@ func newApp( if err != nil { panic(err) } + var oracleGenState oracletypes.GenesisState app.AppCodec().MustUnmarshalJSON(app.DefaultGenesis()[oracletypes.ModuleName], &oracleGenState) go func() { diff --git a/tests/e2e/e2e_setup_test.go b/tests/e2e/e2e_setup_test.go index 10c894f9..68ca2db3 100644 --- a/tests/e2e/e2e_setup_test.go +++ b/tests/e2e/e2e_setup_test.go @@ -1,19 +1,18 @@ -// TODO: Make e2e work with rollkit package e2e -import ( - // "testing" +// import ( +// "testing" - "github.com/stretchr/testify/suite" +// "github.com/stretchr/testify/suite" - "github.com/ojo-network/ojo/tests/e2e/orchestrator" -) +// "github.com/ojo-network/ojo/tests/e2e/orchestrator" +// ) -type IntegrationTestSuite struct { - suite.Suite +// type IntegrationTestSuite struct { +// suite.Suite - orchestrator *orchestrator.Orchestrator -} +// orchestrator *orchestrator.Orchestrator +// } // func TestIntegrationTestSuite(t *testing.T) { // suite.Run(t, new(IntegrationTestSuite)) diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go index cde9c913..39fb722d 100644 --- a/tests/e2e/e2e_test.go +++ b/tests/e2e/e2e_test.go @@ -1,17 +1,16 @@ -// TODO: Make e2e work with rollkit package e2e -import ( -// "time" +// import ( +// "time" -// "cosmossdk.io/math" -// sdk "github.com/cosmos/cosmos-sdk/types" -// "github.com/ojo-network/ojo/client/tx" -// "github.com/ojo-network/ojo/tests/grpc" -// airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" +// "cosmossdk.io/math" +// sdk "github.com/cosmos/cosmos-sdk/types" +// "github.com/ojo-network/ojo/client/tx" +// "github.com/ojo-network/ojo/tests/grpc" +// airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" -// appparams "github.com/ojo-network/ojo/app/params" -) +// appparams "github.com/ojo-network/ojo/app/params" +// ) // // TestMedians queries for the oracle params, collects historical // // prices based on those params, checks that the stored medians and diff --git a/tests/e2e/orchestrator/orchestrator.go b/tests/e2e/orchestrator/orchestrator.go index d15c100b..eb2288cf 100644 --- a/tests/e2e/orchestrator/orchestrator.go +++ b/tests/e2e/orchestrator/orchestrator.go @@ -4,8 +4,6 @@ import ( "context" "encoding/json" "fmt" - "io" - "net/http" "os" "path/filepath" "strings" @@ -18,6 +16,7 @@ import ( appparams "github.com/ojo-network/ojo/app/params" "github.com/ojo-network/ojo/client" + "cosmossdk.io/log" cmtconfig "github.com/cometbft/cometbft/config" cmtjson "github.com/cometbft/cometbft/libs/json" rpchttp "github.com/cometbft/cometbft/rpc/client/http" @@ -35,6 +34,7 @@ import ( govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" oracletypes "github.com/ojo-network/ojo/x/oracle/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) const ( @@ -44,11 +44,6 @@ const ( ojoGrpcPort = "9090" ojoMaxStartupTime = 40 // seconds - // TODO: update original pf instance with sdk 0.47 - priceFeederContainerRepo = "ghcr.io/ojo-network/price-feeder-ojo-47" - priceFeederServerPort = "7171/tcp" - priceFeederMaxStartupTime = 20 // seconds - initBalanceStr = "510000000000" + appparams.BondDenom ) @@ -57,7 +52,6 @@ type Orchestrator struct { chain *chain dkrPool *dockertest.Pool dkrNet *dockertest.Network - priceFeederResource *dockertest.Resource OjoClient *client.OjoClient // signs tx with val[0] AirdropClient *client.OjoClient // signs tx with account[0] } @@ -76,7 +70,7 @@ func (o *Orchestrator) InitResources(t *testing.T) { db := dbm.NewMemDB() app := app.New( - nil, + log.NewNopLogger(), db, nil, true, @@ -115,15 +109,11 @@ func (o *Orchestrator) InitResources(t *testing.T) { o.runValidators(t) o.initOjoClient(t) o.initAirdropClient(t) - o.delegatePriceFeederVoting(t) - o.runPriceFeeder(t) } func (o *Orchestrator) TearDownResources(t *testing.T) { t.Log("tearing down e2e integration test suite...") - require.NoError(t, o.dkrPool.Purge(o.priceFeederResource)) - for _, val := range o.chain.validators { require.NoError(t, o.dkrPool.Purge(val.dockerResource)) } @@ -223,6 +213,19 @@ func (o *Orchestrator) initGenesis(t *testing.T) { require.NoError(t, err) appGenState[govtypes.ModuleName] = bz + // Staking + var stakingGenState stakingtypes.GenesisState + require.NoError(t, o.chain.cdc.UnmarshalJSON(appGenState[stakingtypes.ModuleName], &stakingGenState)) + + stakingGenState.Params.BondDenom = appparams.BondDenom + + bz, err = o.chain.cdc.MarshalJSON(&stakingGenState) + require.NoError(t, err) + appGenState[stakingtypes.ModuleName] = bz + + // Consensus + genDoc.Consensus.Params.ABCI.VoteExtensionsEnableHeight = 2 + // Genesis Txs var genUtilGenState genutiltypes.GenesisState require.NoError(t, o.chain.cdc.UnmarshalJSON(appGenState[genutiltypes.ModuleName], &genUtilGenState)) @@ -231,7 +234,6 @@ func (o *Orchestrator) initGenesis(t *testing.T) { for i, val := range o.chain.validators { var createValmsg sdk.Msg if i == 2 { - createValmsg, err = val.buildCreateValidatorMsg(majorityValidatorStake) } else { createValmsg, err = val.buildCreateValidatorMsg(minorityValidatorStake) } @@ -319,16 +321,29 @@ func (o *Orchestrator) runValidators(t *testing.T) { proposalsDirectory, err := proposalsDirectory() require.NoError(t, err) + priceFeederConfigDirectory, err := priceFeederConfigDirectory() + require.NoError(t, err) for _, val := range o.chain.validators { + // Define command-line arguments for price feeder configuration + priceFeederConfigArgs := []string{ + "start", + "--pricefeeder.config_path=/root/pricefeeder/price-feeder.example.toml", + "--pricefeeder.chain_config=false", + "--pricefeeder.log_level=info", + "--pricefeeder.oracle_tick_time=5s", + } + runOpts := &dockertest.RunOptions{ Name: val.instanceName(), NetworkID: o.dkrNet.Network.ID, Mounts: []string{ fmt.Sprintf("%s/:/root/.ojo", val.configDir()), fmt.Sprintf("%s/:/root/proposals", proposalsDirectory), + fmt.Sprintf("%s/:/root/pricefeeder/price-feeder.example.toml", priceFeederConfigDirectory), }, Repository: ojoContainerRepo, + Cmd: priceFeederConfigArgs, } // expose the first validator @@ -387,105 +402,6 @@ func (o *Orchestrator) runValidators(t *testing.T) { } } -func (o *Orchestrator) delegatePriceFeederVoting(t *testing.T) { - delegateAddr, err := o.chain.validators[0].keyInfo.GetAddress() - require.NoError(t, err) - _, err = o.OjoClient.TxClient.TxDelegateFeedConsent(delegateAddr) - require.NoError(t, err) -} - -func (o *Orchestrator) runPriceFeeder(t *testing.T) { - t.Log("starting price-feeder container...") - - votingVal := o.chain.validators[1] - votingValAddr, err := votingVal.keyInfo.GetAddress() - require.NoError(t, err) - - delegateVal := o.chain.validators[0] - delegateValAddr, err := delegateVal.keyInfo.GetAddress() - require.NoError(t, err) - - grpcEndpoint := fmt.Sprintf("tcp://%s:%s", delegateVal.instanceName(), ojoGrpcPort) - cmtrpcEndpoint := fmt.Sprintf("http://%s:%s", delegateVal.instanceName(), ojoTmrpcPort) - - o.priceFeederResource, err = o.dkrPool.RunWithOptions( - &dockertest.RunOptions{ - Name: "price-feeder", - NetworkID: o.dkrNet.Network.ID, - Repository: priceFeederContainerRepo, - Mounts: []string{ - fmt.Sprintf("%s/:/root/.ojo", delegateVal.configDir()), - }, - PortBindings: map[docker.Port][]docker.PortBinding{ - "7171/tcp": {{HostIP: "", HostPort: "7171"}}, - }, - Env: []string{ - fmt.Sprintf("PRICE_FEEDER_PASS=%s", keyringPassphrase), - fmt.Sprintf("ACCOUNT_ADDRESS=%s", delegateValAddr), - fmt.Sprintf("ACCOUNT_VALIDATOR=%s", sdk.ValAddress(votingValAddr)), - fmt.Sprintf("KEYRING_DIR=%s", "/root/.ojo"), - fmt.Sprintf("ACCOUNT_CHAIN_ID=%s", o.chain.id), - fmt.Sprintf("RPC_GRPC_ENDPOINT=%s", grpcEndpoint), - fmt.Sprintf("RPC_TMRPC_ENDPOINT=%s", cmtrpcEndpoint), - }, - Cmd: []string{"--skip-provider-check", "--log-level=debug"}, - }, - noRestart, - ) - require.NoError(t, err) - - endpoint := fmt.Sprintf("http://%s/api/v1/prices", o.priceFeederResource.GetHostPort(priceFeederServerPort)) - - checkHealth := func() bool { - resp, err := http.Get(endpoint) - if err != nil { - t.Log("Price feeder endpoint not available", err, endpoint) - return false - } - - defer resp.Body.Close() - - bz, err := io.ReadAll(resp.Body) - if err != nil { - t.Log("Can't get price feeder response", err) - return false - } - - var respBody map[string]interface{} - if err := json.Unmarshal(bz, &respBody); err != nil { - t.Log("Can't unmarshal price feed", err) - return false - } - - prices, ok := respBody["prices"].(map[string]interface{}) - if !ok { - t.Log("price feeder: no prices") - return false - } - - return len(prices) > 0 - } - - isHealthy := false - for i := 0; i < priceFeederMaxStartupTime; i++ { - isHealthy = checkHealth() - if isHealthy { - break - } - time.Sleep(time.Second) - } - - if !isHealthy { - err := o.outputLogs(o.priceFeederResource) - if err != nil { - t.Log("Error retrieving price feeder logs", err) - } - t.Fatal("price-feeder not healthy") - } - - t.Logf("started price-feeder container: %s", o.priceFeederResource.Container.ID) -} - func (o *Orchestrator) initOjoClient(t *testing.T) { var err error o.OjoClient, err = client.NewOjoClient( @@ -541,3 +457,18 @@ func proposalsDirectory() (string, error) { return absoluteAdjacentDirPath, nil } + +func priceFeederConfigDirectory() (string, error) { + workingDir, err := os.Getwd() + if err != nil { + return "", err + } + + priceFeederConfigDirPath := filepath.Join(workingDir, "../../pricefeeder/price-feeder.example.toml") + absoluteAdjacentDirPath, err := filepath.Abs(priceFeederConfigDirPath) + if err != nil { + return "", err + } + + return absoluteAdjacentDirPath, nil +} diff --git a/tests/e2e/orchestrator/validator.go b/tests/e2e/orchestrator/validator.go index 0a32f382..4d14c654 100644 --- a/tests/e2e/orchestrator/validator.go +++ b/tests/e2e/orchestrator/validator.go @@ -25,6 +25,7 @@ import ( txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" "github.com/cosmos/cosmos-sdk/x/genutil" + "github.com/cosmos/cosmos-sdk/x/genutil/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/ory/dockertest/v3" @@ -83,6 +84,9 @@ func (v *validator) init(gen map[string]json.RawMessage) error { genesis.ChainID = v.chain.id genesis.AppState = appState + genesis.Consensus = &types.ConsensusGenesis{ + Validators: nil, + } if err = genutil.ExportGenesisFile(genesis, config.GenesisFile()); err != nil { return fmt.Errorf("failed to export app genesis state: %w", err) From c5f313aaf30da64331f2247cecae62fa3ad83bdb Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 09:51:44 -0600 Subject: [PATCH 17/27] pr comments --- .gitignore | 7 ++++++- config.yml | 2 +- tests/e2e/orchestrator/orchestrator.go | 18 +++++++++--------- x/oracle/abci/abci_test.go | 8 ++++++-- x/oracle/abci/preblocker.go | 6 +++++- x/oracle/abci/proposal.go | 8 ++++++++ x/oracle/abci/voteextension.go | 4 ++++ 7 files changed, 39 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 9942d37a..6b876a3b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,9 @@ release/ .idea/ .vscode/ .DS_Store -build \ No newline at end of file +build +buf.work.yaml +proto/buf.gen.pulsar.yaml +proto/buf.gen.sta.yaml +proto/buf.gen.swagger.yaml +proto/buf.gen.ts.yaml diff --git a/config.yml b/config.yml index 3d6a8c70..c6bed592 100644 --- a/config.yml +++ b/config.yml @@ -43,4 +43,4 @@ validators: bonded: 33500000000000uojo app: pricefeeder: - config_path: "PATH TO PRICE FEEDER CONFIG HERE" + config_path: "./pricefeeder/price-feeder.example.toml" diff --git a/tests/e2e/orchestrator/orchestrator.go b/tests/e2e/orchestrator/orchestrator.go index eb2288cf..035f28fa 100644 --- a/tests/e2e/orchestrator/orchestrator.go +++ b/tests/e2e/orchestrator/orchestrator.go @@ -32,9 +32,9 @@ import ( govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govtypesv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" airdroptypes "github.com/ojo-network/ojo/x/airdrop/types" oracletypes "github.com/ojo-network/ojo/x/oracle/types" - stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) const ( @@ -48,12 +48,12 @@ const ( ) type Orchestrator struct { - tmpDirs []string - chain *chain - dkrPool *dockertest.Pool - dkrNet *dockertest.Network - OjoClient *client.OjoClient // signs tx with val[0] - AirdropClient *client.OjoClient // signs tx with account[0] + tmpDirs []string + chain *chain + dkrPool *dockertest.Pool + dkrNet *dockertest.Network + OjoClient *client.OjoClient // signs tx with val[0] + AirdropClient *client.OjoClient // signs tx with account[0] } // SetupSuite initializes and runs all the resources needed for the @@ -326,7 +326,7 @@ func (o *Orchestrator) runValidators(t *testing.T) { for _, val := range o.chain.validators { // Define command-line arguments for price feeder configuration - priceFeederConfigArgs := []string{ + priceFeederConfigArgs := []string{ "start", "--pricefeeder.config_path=/root/pricefeeder/price-feeder.example.toml", "--pricefeeder.chain_config=false", @@ -343,7 +343,7 @@ func (o *Orchestrator) runValidators(t *testing.T) { fmt.Sprintf("%s/:/root/pricefeeder/price-feeder.example.toml", priceFeederConfigDirectory), }, Repository: ojoContainerRepo, - Cmd: priceFeederConfigArgs, + Cmd: priceFeederConfigArgs, } // expose the first validator diff --git a/x/oracle/abci/abci_test.go b/x/oracle/abci/abci_test.go index a130f107..3bb01993 100644 --- a/x/oracle/abci/abci_test.go +++ b/x/oracle/abci/abci_test.go @@ -18,6 +18,10 @@ import ( "github.com/ojo-network/price-feeder/oracle/types" ) +var ( + VoteThreshold = math.LegacyMustNewDecFromStr("0.4") +) + type IntegrationTestSuite struct { suite.Suite @@ -28,7 +32,7 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupTest() { s.app, s.ctx, s.keys = integration.SetupAppWithContext(s.T()) - s.app.OracleKeeper.SetVoteThreshold(s.ctx, math.LegacyMustNewDecFromStr("0.4")) + s.app.OracleKeeper.SetVoteThreshold(s.ctx, VoteThreshold) } func TestAbciTestSuite(t *testing.T) { @@ -44,7 +48,7 @@ func MockPriceFeeder() *pricefeeder.PriceFeeder { zerolog.Nop(), client.OracleClient{}, providers, - time.Second*10, + time.Second*5, deviations, providerEndpointsMap, false, diff --git a/x/oracle/abci/preblocker.go b/x/oracle/abci/preblocker.go index 9d9f83f3..1bafd76e 100644 --- a/x/oracle/abci/preblocker.go +++ b/x/oracle/abci/preblocker.go @@ -23,6 +23,9 @@ func NewPreBlockHandler(logger log.Logger, keeper keeper.Keeper) *PreBlockHandle } } +// PreBlocker is run before finalize block to update the aggregrate exchange rate votes on the oracle module +// that were verified by the vote etension handler so that the exchange rate votes are available during the +// entire block execution (from BeginBlock). func (h *PreBlockHandler) PreBlocker() sdk.PreBlocker { return func(ctx sdk.Context, req *cometabci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) { if req == nil { @@ -49,7 +52,8 @@ func (h *PreBlockHandler) PreBlocker() sdk.PreBlocker { for _, exchangeRateVote := range injectedVoteExtTx.ExchangeRateVotes { valAddr, err := sdk.ValAddressFromBech32(exchangeRateVote.Voter) if err != nil { - return nil, err + h.logger.Error("failed to get voter address", "err", err) + continue } h.keeper.SetAggregateExchangeRateVote(ctx, valAddr, exchangeRateVote) } diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index ad401914..8c1d81b5 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -40,6 +40,11 @@ func NewProposalHandler( } } +// PrepareProposalHandler is called only on the selected validator as "block proposer" (selected by CometBFT, read more +// about this process here: https://docs.cometbft.com/v0.38/spec/consensus/proposer-selection). The block proposer is in +// charge of creating the next block by selecting the transactions from the mempool, and in this method it will create an +// extra transaction using the vote extension from the previous block which are only available on the next height at which +// vote extensions were enabled. func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *cometabci.RequestPrepareProposal) (*cometabci.ResponsePrepareProposal, error) { if req == nil { @@ -100,6 +105,9 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { } } +// ProcessProposalHandler is called on all validators, and they can verify if the proposed block is valid. In case an +// invalid block is being proposed validators can reject it, causing a new round of PrepareProposal to happen. This +// step MUST be deterministic. func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { return func(ctx sdk.Context, req *cometabci.RequestProcessProposal) (*cometabci.ResponseProcessProposal, error) { if req == nil { diff --git a/x/oracle/abci/voteextension.go b/x/oracle/abci/voteextension.go index 1c7f16e7..12f4b230 100644 --- a/x/oracle/abci/voteextension.go +++ b/x/oracle/abci/voteextension.go @@ -39,6 +39,8 @@ func NewVoteExtensionHandler( } } +// ExtendVoteHandler creates an OracleVoteExtension using the prices fetched from the price feeder +// service. It will filter out exchange rates that are not part of the oracle module's accept list. func (h *VoteExtensionHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return func(ctx sdk.Context, req *cometabci.RequestExtendVote) (resp *cometabci.ResponseExtendVote, err error) { defer func() { @@ -112,6 +114,8 @@ func (h *VoteExtensionHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { } } +// VerifyVoteExtensionHandler validates the OracleVoteExtension created by the ExtendVoteHandler. It +// verifies that the vote extension can unmarshal correctly and is for the correct height. func (h *VoteExtensionHandler) VerifyVoteExtensionHandler() sdk.VerifyVoteExtensionHandler { return func(ctx sdk.Context, req *cometabci.RequestVerifyVoteExtension) ( *cometabci.ResponseVerifyVoteExtension, From 26084fbe3607706ee827a8cabb4d2ddd3bf2f276 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 10:00:45 -0600 Subject: [PATCH 18/27] git rm cached ignore files --- buf.work.yaml | 3 --- proto/buf.gen.pulsar.yaml | 22 ---------------------- proto/buf.gen.sta.yaml | 15 --------------- proto/buf.gen.swagger.yaml | 14 -------------- proto/buf.gen.ts.yaml | 18 ------------------ 5 files changed, 72 deletions(-) delete mode 100644 buf.work.yaml delete mode 100644 proto/buf.gen.pulsar.yaml delete mode 100644 proto/buf.gen.sta.yaml delete mode 100644 proto/buf.gen.swagger.yaml delete mode 100644 proto/buf.gen.ts.yaml diff --git a/buf.work.yaml b/buf.work.yaml deleted file mode 100644 index 1878b341..00000000 --- a/buf.work.yaml +++ /dev/null @@ -1,3 +0,0 @@ -version: v1 -directories: - - proto diff --git a/proto/buf.gen.pulsar.yaml b/proto/buf.gen.pulsar.yaml deleted file mode 100644 index e8fffdb2..00000000 --- a/proto/buf.gen.pulsar.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# This file is auto-generated from Ignite. You can edit -# the file content but do not change the file name or path. -# -# buf.gen.pulsar.yaml -# -version: v1 -managed: - enabled: true - go_package_prefix: - default: cosmossdk.io/api - except: - - buf.build/googleapis/googleapis - - buf.build/cosmos/gogo-proto - - buf.build/cosmos/cosmos-proto - override: -plugins: - - name: go-pulsar - out: ./api - opt: paths=source_relative - - name: go-grpc - out: ./api - opt: paths=source_relative diff --git a/proto/buf.gen.sta.yaml b/proto/buf.gen.sta.yaml deleted file mode 100644 index 4444f5e7..00000000 --- a/proto/buf.gen.sta.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# This file is auto-generated from Ignite. You can edit -# the file content but do not change the file name or path. -# -# buf.gen.sta.yaml -# -version: v1 -plugins: - - name: openapiv2 - out: . - opt: - - logtostderr=true - - openapi_naming_strategy=simple - - ignore_comments=true - - simple_operation_ids=false - - json_names_for_fields=false diff --git a/proto/buf.gen.swagger.yaml b/proto/buf.gen.swagger.yaml deleted file mode 100644 index 58d30d86..00000000 --- a/proto/buf.gen.swagger.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# This file is auto-generated from Ignite. You can edit -# the file content but do not change the file name or path. -# -# buf.gen.swagger.yaml -# -version: v1 -plugins: - - name: openapiv2 - out: . - opt: - - logtostderr=true - - openapi_naming_strategy=fqn - - json_names_for_fields=false - - generate_unbound_methods=true \ No newline at end of file diff --git a/proto/buf.gen.ts.yaml b/proto/buf.gen.ts.yaml deleted file mode 100644 index c484fb3a..00000000 --- a/proto/buf.gen.ts.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# This file is auto-generated from Ignite. You can edit -# the file content but do not change the file name or path. -# -# buf.gen.ts.yaml -# -version: v1 -managed: - enabled: true -plugins: - - plugin: buf.build/community/stephenh-ts-proto - out: . - opt: - - logtostderr=true - - allow_merge=true - - json_names_for_fields=false - - ts_proto_opt=snakeToCamel=true - - ts_proto_opt=esModuleInterop=true - - ts_proto_out=. From fd32880f78dae9469b2175a4215c50529ee03983 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 10:15:50 -0600 Subject: [PATCH 19/27] lint --- tests/e2e/orchestrator/orchestrator.go | 1 + x/oracle/abci/proposal.go | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/e2e/orchestrator/orchestrator.go b/tests/e2e/orchestrator/orchestrator.go index 035f28fa..4460b8c2 100644 --- a/tests/e2e/orchestrator/orchestrator.go +++ b/tests/e2e/orchestrator/orchestrator.go @@ -234,6 +234,7 @@ func (o *Orchestrator) initGenesis(t *testing.T) { for i, val := range o.chain.validators { var createValmsg sdk.Msg if i == 2 { + createValmsg, err = val.buildCreateValidatorMsg(majorityValidatorStake) } else { createValmsg, err = val.buildCreateValidatorMsg(minorityValidatorStake) } diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index 8c1d81b5..f0eefac9 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -40,11 +40,11 @@ func NewProposalHandler( } } -// PrepareProposalHandler is called only on the selected validator as "block proposer" (selected by CometBFT, read more -// about this process here: https://docs.cometbft.com/v0.38/spec/consensus/proposer-selection). The block proposer is in -// charge of creating the next block by selecting the transactions from the mempool, and in this method it will create an -// extra transaction using the vote extension from the previous block which are only available on the next height at which -// vote extensions were enabled. +// PrepareProposalHandler is called only on the selected validator as "block proposer" (selected by CometBFT, read +// more about this process here: https://docs.cometbft.com/v0.38/spec/consensus/proposer-selection). The block +// proposer is in charge of creating the next block by selecting the transactions from the mempool, and in this +// method it will create an extra transaction using the vote extension from the previous block which are only +// available on the next height at which vote extensions were enabled. func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return func(ctx sdk.Context, req *cometabci.RequestPrepareProposal) (*cometabci.ResponsePrepareProposal, error) { if req == nil { From 87c9aeb40bef70ae8fed766bbd4e641b16bfd53e Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 12:29:20 -0600 Subject: [PATCH 20/27] import latest pf version --- go.mod | 2 +- go.sum | 4 ++-- pricefeeder/config.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 63ec3e41..7bd2fdbd 100644 --- a/go.mod +++ b/go.mod @@ -36,7 +36,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 github.com/mgechev/revive v1.3.6 github.com/mitchellh/mapstructure v1.5.0 - github.com/ojo-network/price-feeder v0.1.11-0.20240403153904-aeda5a5840a6 + github.com/ojo-network/price-feeder v0.2.0 github.com/ory/dockertest/v3 v3.10.0 github.com/rs/zerolog v1.32.0 github.com/spf13/cast v1.6.0 diff --git a/go.sum b/go.sum index 7bb9f454..ea603bb1 100644 --- a/go.sum +++ b/go.sum @@ -1092,8 +1092,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= -github.com/ojo-network/price-feeder v0.1.11-0.20240403153904-aeda5a5840a6 h1:2txECFIt4gxKj1ryBbmjv3H5FVgXByZUr+vcm9hbh5g= -github.com/ojo-network/price-feeder v0.1.11-0.20240403153904-aeda5a5840a6/go.mod h1:2xHrCcUMPoozsvst9785vToD7/U05OOAAl0NvnMYaTg= +github.com/ojo-network/price-feeder v0.2.0 h1:1D+0K19xUlmEPUxAeyG0W+CWjBvSOSdwoMYcQ2+u9dM= +github.com/ojo-network/price-feeder v0.2.0/go.mod h1:2xHrCcUMPoozsvst9785vToD7/U05OOAAl0NvnMYaTg= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= diff --git a/pricefeeder/config.go b/pricefeeder/config.go index b02b3783..8e0c39aa 100644 --- a/pricefeeder/config.go +++ b/pricefeeder/config.go @@ -15,7 +15,7 @@ const ( config_path = "" # Specifies whether the currency pair providers and currency deviation threshold values should # be read from the oracle module's on chain parameters or the price feeder config -chain_config = true +chain_config = false # Log level of price feeder process log_level = "info" # Time interval that the price feeder's oracle process waits before fetching for new prices From 97c881d3026ccf6a862a3c1352acc0e927b1b2f8 Mon Sep 17 00:00:00 2001 From: ryanbajollari <54822716+rbajollari@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:32:17 -0400 Subject: [PATCH 21/27] Update .gitignore Co-authored-by: Adam Wozniak <29418299+adamewozniak@users.noreply.github.com> --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6b876a3b..f20e0388 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ release/ .vscode/ .DS_Store build +# files generated by ignite cli buf.work.yaml proto/buf.gen.pulsar.yaml proto/buf.gen.sta.yaml From 5ae25dd3dd25768d2a2d8103a4db2509a06de160 Mon Sep 17 00:00:00 2001 From: ryanbajollari <54822716+rbajollari@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:32:34 -0400 Subject: [PATCH 22/27] Update x/oracle/abci/proposal.go Co-authored-by: Adam Wozniak <29418299+adamewozniak@users.noreply.github.com> --- x/oracle/abci/proposal.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index f0eefac9..26d226f6 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -88,7 +88,7 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { return nil, errors.New("failed to encode injected vote extension tx") } - // Inject a "fake" tx into the proposal s.t. validators can decode, verify, + // Inject a placeholder tx into the proposal s.t. validators can decode, verify, // and store the oracle exchange rate votes. proposalTxs = append([][]byte{bz}, proposalTxs...) } From 8b676754b1d8779eead28ab743cec96003ec295f Mon Sep 17 00:00:00 2001 From: ryanbajollari <54822716+rbajollari@users.noreply.github.com> Date: Tue, 9 Apr 2024 14:37:56 -0400 Subject: [PATCH 23/27] Update x/oracle/abci/voteextension.go Co-authored-by: Adam Wozniak <29418299+adamewozniak@users.noreply.github.com> --- x/oracle/abci/voteextension.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/oracle/abci/voteextension.go b/x/oracle/abci/voteextension.go index 12f4b230..406f2a63 100644 --- a/x/oracle/abci/voteextension.go +++ b/x/oracle/abci/voteextension.go @@ -82,7 +82,7 @@ func (h *VoteExtensionHandler) ExtendVoteHandler() sdk.ExtendVoteHandler { return nil, err } - // Filter out rates which aren't included in the AcceptList + // Filter out rates which aren't included in the AcceptList. acceptList := h.oracleKeeper.AcceptList(ctx) filteredDecCoins := sdk.DecCoins{} for _, decCoin := range exchangeRates { From e47a9e9e7b1922ac693f2ab0de8d461ea1ec5112 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 14:26:44 -0600 Subject: [PATCH 24/27] round 2 pr comments --- pricefeeder/config.go | 2 +- x/oracle/abci/endblocker_test.go | 6 +- x/oracle/abci/proposal.go | 8 +-- x/oracle/keeper/msg_server_test.go | 110 ++++++----------------------- x/oracle/simulations/operations.go | 2 +- x/oracle/types/asset.go | 37 ++++++---- x/oracle/types/errors.go | 3 + x/oracle/types/params.go | 107 +++++++++++++++++++++++++++- x/oracle/types/params_test.go | 14 ++-- 9 files changed, 173 insertions(+), 116 deletions(-) diff --git a/pricefeeder/config.go b/pricefeeder/config.go index 8e0c39aa..b02b3783 100644 --- a/pricefeeder/config.go +++ b/pricefeeder/config.go @@ -15,7 +15,7 @@ const ( config_path = "" # Specifies whether the currency pair providers and currency deviation threshold values should # be read from the oracle module's on chain parameters or the price feeder config -chain_config = false +chain_config = true # Log level of price feeder process log_level = "info" # Time interval that the price feeder's oracle process waits before fetching for new prices diff --git a/x/oracle/abci/endblocker_test.go b/x/oracle/abci/endblocker_test.go index 37e3bc50..e7a75786 100644 --- a/x/oracle/abci/endblocker_test.go +++ b/x/oracle/abci/endblocker_test.go @@ -166,7 +166,7 @@ func (s *IntegrationTestSuite) TestEndBlockerValidatorRewards() { ctx = ctx.WithBlockHeight(int64(app.OracleKeeper.SlashWindow(ctx))) abci.EndBlocker(ctx, app.OracleKeeper) - app.OracleKeeper.SetMandatoryList(ctx, types.DenomList{ + denomList := types.DenomList{ { BaseDenom: appparams.BondDenom, SymbolDenom: appparams.DisplayDenom, @@ -177,7 +177,9 @@ func (s *IntegrationTestSuite) TestEndBlockerValidatorRewards() { SymbolDenom: "atom", Exponent: uint32(6), }, - }) + } + app.OracleKeeper.SetAcceptList(ctx, denomList) + app.OracleKeeper.SetMandatoryList(ctx, denomList) var ( val1DecCoins sdk.DecCoins diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index 26d226f6..cc999926 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -2,7 +2,6 @@ package abci import ( "encoding/json" - "errors" "fmt" "sort" @@ -82,10 +81,11 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { } // TODO: Switch from stdlib JSON encoding to a more performant mechanism. + // REF: https://github.com/ojo-network/ojo/issues/411 bz, err := json.Marshal(injectedVoteExtTx) if err != nil { h.logger.Error("failed to encode injected vote extension tx", "err", err) - return nil, errors.New("failed to encode injected vote extension tx") + return nil, oracletypes.ErrEncodeInjVoteExt } // Inject a placeholder tx into the proposal s.t. validators can decode, verify, @@ -220,7 +220,7 @@ func (h *ProposalHandler) verifyExchangeRateVotes( generatedVotes []oracletypes.AggregateExchangeRateVote, ) error { if len(injectedVotes) != len(generatedVotes) { - return errors.New("number of exchange rate votes in vote extension and extended commit info are not equal") + return oracletypes.ErrNonEqualInjVotesLen } for i := range injectedVotes { @@ -228,7 +228,7 @@ func (h *ProposalHandler) verifyExchangeRateVotes( generatedVote := generatedVotes[i] if injectedVote.Voter != generatedVote.Voter || !injectedVote.ExchangeRates.Equal(generatedVote.ExchangeRates) { - return errors.New("injected exhange rate votes and generated exchange votes are not equal") + return oracletypes.ErrNonEqualInjVotesRates } } diff --git a/x/oracle/keeper/msg_server_test.go b/x/oracle/keeper/msg_server_test.go index 075816c5..f76f328f 100644 --- a/x/oracle/keeper/msg_server_test.go +++ b/x/oracle/keeper/msg_server_test.go @@ -174,23 +174,11 @@ func (s *IntegrationTestSuite) TestMsgServer_UpdateGovParams() { Keys: []string{"AcceptList"}, Height: 9, Changes: types.Params{ - AcceptList: types.DenomList{ - { - BaseDenom: oracletypes.OjoDenom, - SymbolDenom: oracletypes.OjoSymbol, - Exponent: 6, - }, - { - BaseDenom: oracletypes.AtomDenom, - SymbolDenom: oracletypes.AtomSymbol, - Exponent: 6, - }, - { - BaseDenom: "base", - SymbolDenom: "symbol", - Exponent: 6, - }, - }, + AcceptList: append(oracletypes.DefaultAcceptList, types.Denom{ + BaseDenom: "base", + SymbolDenom: "symbol", + Exponent: 6, + }), }, }, }, @@ -207,18 +195,7 @@ func (s *IntegrationTestSuite) TestMsgServer_UpdateGovParams() { Keys: []string{"MandatoryList"}, Height: 9, Changes: types.Params{ - MandatoryList: types.DenomList{ - { - BaseDenom: oracletypes.OjoDenom, - SymbolDenom: oracletypes.OjoSymbol, - Exponent: 6, - }, - { - BaseDenom: oracletypes.AtomDenom, - SymbolDenom: oracletypes.AtomSymbol, - Exponent: 6, - }, - }, + MandatoryList: oracletypes.DefaultMandatoryList, }, }, }, @@ -258,20 +235,10 @@ func (s *IntegrationTestSuite) TestMsgServer_UpdateGovParams() { Keys: []string{"RewardBands"}, Height: 9, Changes: types.Params{ - RewardBands: types.RewardBandList{ - { - SymbolDenom: types.OjoSymbol, - RewardBand: math.LegacyNewDecWithPrec(2, 2), - }, - { - SymbolDenom: types.AtomSymbol, - RewardBand: math.LegacyNewDecWithPrec(2, 2), - }, - { - SymbolDenom: "symbol", - RewardBand: math.LegacyNewDecWithPrec(2, 2), - }, - }, + RewardBands: append(oracletypes.DefaultRewardBands(), oracletypes.RewardBand{ + SymbolDenom: "symbol", + RewardBand: math.LegacyNewDecWithPrec(2, 2), + }), }, }, }, @@ -430,55 +397,22 @@ func (s *IntegrationTestSuite) TestMsgServer_UpdateGovParams() { switch tc.name { case "valid accept list": acceptList := s.app.OracleKeeper.AcceptList(s.ctx) - s.Require().Equal(acceptList, types.DenomList{ - { - BaseDenom: oracletypes.OjoDenom, - SymbolDenom: oracletypes.OjoSymbol, - Exponent: 6, - }, - { - BaseDenom: oracletypes.AtomDenom, - SymbolDenom: oracletypes.AtomSymbol, - Exponent: 6, - }, - { - BaseDenom: "base", - SymbolDenom: "symbol", - Exponent: 6, - }, - }.Normalize()) + s.Require().Equal(acceptList, append(oracletypes.DefaultAcceptList, types.Denom{ + BaseDenom: "base", + SymbolDenom: "symbol", + Exponent: 6, + }).Normalize()) case "valid mandatory list": mandatoryList := s.app.OracleKeeper.MandatoryList(s.ctx) - s.Require().Equal(mandatoryList, types.DenomList{ - { - BaseDenom: oracletypes.OjoDenom, - SymbolDenom: oracletypes.OjoSymbol, - Exponent: 6, - }, - { - BaseDenom: oracletypes.AtomDenom, - SymbolDenom: oracletypes.AtomSymbol, - Exponent: 6, - }, - }.Normalize()) + s.Require().Equal(mandatoryList, oracletypes.DefaultMandatoryList.Normalize()) case "valid reward band list": rewardBand := s.app.OracleKeeper.RewardBands(s.ctx) - s.Require().Equal(rewardBand, types.RewardBandList{ - { - SymbolDenom: types.OjoSymbol, - RewardBand: math.LegacyNewDecWithPrec(2, 2), - }, - { - SymbolDenom: types.AtomSymbol, - RewardBand: math.LegacyNewDecWithPrec(2, 2), - }, - { - SymbolDenom: "symbol", - RewardBand: math.LegacyNewDecWithPrec(2, 2), - }, - }) + s.Require().Equal(rewardBand, append(oracletypes.DefaultRewardBands(), oracletypes.RewardBand{ + SymbolDenom: "symbol", + RewardBand: math.LegacyNewDecWithPrec(2, 2), + })) case "multiple valid params": votePeriod := s.app.OracleKeeper.VotePeriod(s.ctx) @@ -870,7 +804,7 @@ func (s *IntegrationTestSuite) TestMsgServer_GovRemoveCurrencyPairProviders() { }, { BaseDenom: types.OjoSymbol, - QuoteDenom: types.USDDenom, + QuoteDenom: types.USDSymbol, Providers: []string{ "binance", "coinbase", @@ -1012,7 +946,7 @@ func (s *IntegrationTestSuite) TestMsgServer_GovRemoveCurrencyPairProviders() { s.Require().Equal(types.CurrencyPairProvidersList{ { BaseDenom: types.OjoSymbol, - QuoteDenom: types.USDDenom, + QuoteDenom: types.USDSymbol, Providers: []string{ "binance", "coinbase", diff --git a/x/oracle/simulations/operations.go b/x/oracle/simulations/operations.go index ee69ff10..47660233 100644 --- a/x/oracle/simulations/operations.go +++ b/x/oracle/simulations/operations.go @@ -31,7 +31,7 @@ const ( ) var ( - acceptList = []string{types.OjoSymbol, types.USDDenom} + acceptList = []string{types.OjoSymbol, types.USDSymbol} ojoPrice = math.LegacyMustNewDecFromStr("25.71") ) diff --git a/x/oracle/types/asset.go b/x/oracle/types/asset.go index 158aaef0..54587b50 100644 --- a/x/oracle/types/asset.go +++ b/x/oracle/types/asset.go @@ -8,20 +8,29 @@ import ( ) const ( - OjoDenom string = appparams.BondDenom - OjoSymbol string = "OJO" - OjoExponent = uint32(6) - AtomDenom string = "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9" - AtomSymbol string = "ATOM" - AtomExponent = uint32(6) - USDDenom string = "USD" - BlocksPerMinute = uint64(10) - BlocksPerHour = BlocksPerMinute * 60 - BlocksPerDay = BlocksPerHour * 24 - BlocksPerWeek = BlocksPerDay * 7 - BlocksPerMonth = BlocksPerDay * 30 - BlocksPerYear = BlocksPerDay * 365 - MicroUnit = int64(1e6) + OjoDenom string = appparams.BondDenom + OjoSymbol string = "OJO" + OjoExponent = uint32(6) + AtomDenom string = "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9" + AtomSymbol string = "ATOM" + AtomExponent = uint32(6) + BitcoinDenom string = "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9" + BitcoinSymbol string = "BTC" + BitcoinExponent = uint32(18) + EthereumDenom string = "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9" + EthereumSymbol string = "ETH" + EthereumExponent = uint32(18) + USDTDenom string = "ibc/C4CFF46FD6DE35CA4CF4CE031E643C8FDC9BA4B99AE598E9B0ED98FE3A2319F9" + USDTSymbol string = "USDT" + USDTExponent = uint32(18) + USDSymbol string = "USD" + BlocksPerMinute = uint64(10) + BlocksPerHour = BlocksPerMinute * 60 + BlocksPerDay = BlocksPerHour * 24 + BlocksPerWeek = BlocksPerDay * 7 + BlocksPerMonth = BlocksPerDay * 30 + BlocksPerYear = BlocksPerDay * 365 + MicroUnit = int64(1e6) ) type ( diff --git a/x/oracle/types/errors.go b/x/oracle/types/errors.go index fdeac82c..29b98fdd 100644 --- a/x/oracle/types/errors.go +++ b/x/oracle/types/errors.go @@ -34,4 +34,7 @@ var ( ErrNoGovAuthority = errors.Register(ModuleName, 24, "invalid gov authority to perform these changes") ErrInvalidRequest = errors.Register(ModuleName, 25, "invalid request") ErrInvalidParamValue = errors.Register(ModuleName, 26, "invalid oracle param value") + ErrEncodeInjVoteExt = errors.Register(ModuleName, 27, "failed to encode injected vote extension tx") + ErrNonEqualInjVotesLen = errors.Register(ModuleName, 28, "number of exchange rate votes in vote extension and extended commit info are not equal") //nolint: lll + ErrNonEqualInjVotesRates = errors.Register(ModuleName, 29, "injected exhange rate votes and generated exchange votes are not equal") //nolint: lll ) diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index de7c20b9..1bb318dd 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -62,6 +62,21 @@ var ( SymbolDenom: AtomSymbol, Exponent: AtomExponent, }, + { + BaseDenom: USDTDenom, + SymbolDenom: USDTSymbol, + Exponent: USDTExponent, + }, + { + BaseDenom: BitcoinDenom, + SymbolDenom: BitcoinSymbol, + Exponent: BitcoinExponent, + }, + { + BaseDenom: EthereumDenom, + SymbolDenom: EthereumSymbol, + Exponent: EthereumExponent, + }, } DefaultMandatoryList = DenomList{ { @@ -69,6 +84,21 @@ var ( SymbolDenom: AtomSymbol, Exponent: AtomExponent, }, + { + BaseDenom: USDTDenom, + SymbolDenom: USDTSymbol, + Exponent: USDTExponent, + }, + { + BaseDenom: BitcoinDenom, + SymbolDenom: BitcoinSymbol, + Exponent: BitcoinExponent, + }, + { + BaseDenom: EthereumDenom, + SymbolDenom: EthereumSymbol, + Exponent: EthereumExponent, + }, } DefaultSlashFraction = math.LegacyNewDecWithPrec(1, 4) // 0.01% DefaultMinValidPerWindow = math.LegacyNewDecWithPrec(5, 2) // 5% @@ -77,19 +107,68 @@ var ( DefaultCurrencyPairProviders = CurrencyPairProvidersList{ CurrencyPairProviders{ BaseDenom: OjoSymbol, - QuoteDenom: USDDenom, + QuoteDenom: USDSymbol, Providers: []string{ "binance", "coinbase", }, }, + CurrencyPairProviders{ + BaseDenom: USDTSymbol, + QuoteDenom: USDSymbol, + Providers: []string{ + "kraken", + "coinbase", + "crypto", + }, + }, CurrencyPairProviders{ BaseDenom: AtomSymbol, - QuoteDenom: USDDenom, + QuoteDenom: USDSymbol, Providers: []string{ "kraken", }, }, + CurrencyPairProviders{ + BaseDenom: AtomSymbol, + QuoteDenom: USDTSymbol, + Providers: []string{ + "okx", + "bitget", + "gate", + }, + }, + CurrencyPairProviders{ + BaseDenom: BitcoinSymbol, + QuoteDenom: USDSymbol, + Providers: []string{ + "coinbase", + }, + }, + CurrencyPairProviders{ + BaseDenom: BitcoinSymbol, + QuoteDenom: USDTSymbol, + Providers: []string{ + "okx", + "gate", + "bitget", + }, + }, + CurrencyPairProviders{ + BaseDenom: EthereumSymbol, + QuoteDenom: USDSymbol, + Providers: []string{ + "kraken", + }, + }, + CurrencyPairProviders{ + BaseDenom: EthereumSymbol, + QuoteDenom: USDTSymbol, + Providers: []string{ + "okx", + "bitget", + }, + }, } DefaultCurrencyDeviationThresholds = CurrencyDeviationThresholdList{ @@ -97,10 +176,22 @@ var ( BaseDenom: OjoSymbol, Threshold: "2", }, + CurrencyDeviationThreshold{ + BaseDenom: USDTSymbol, + Threshold: "2", + }, CurrencyDeviationThreshold{ BaseDenom: AtomSymbol, Threshold: "2", }, + CurrencyDeviationThreshold{ + BaseDenom: BitcoinSymbol, + Threshold: "2", + }, + CurrencyDeviationThreshold{ + BaseDenom: EthereumSymbol, + Threshold: "2", + }, } ) @@ -120,6 +211,18 @@ func DefaultRewardBands() RewardBandList { SymbolDenom: AtomSymbol, RewardBand: defaultRewardBand, }, + { + SymbolDenom: USDTSymbol, + RewardBand: defaultRewardBand, + }, + { + SymbolDenom: BitcoinSymbol, + RewardBand: defaultRewardBand, + }, + { + SymbolDenom: EthereumSymbol, + RewardBand: defaultRewardBand, + }, } } diff --git a/x/oracle/types/params_test.go b/x/oracle/types/params_test.go index 839eb360..ff65d7d3 100644 --- a/x/oracle/types/params_test.go +++ b/x/oracle/types/params_test.go @@ -147,7 +147,7 @@ func TestValidateCurrencyPairProviders(t *testing.T) { err = validateCurrencyPairProviders( CurrencyPairProvidersList{ CurrencyPairProviders{ - QuoteDenom: USDDenom, + QuoteDenom: USDSymbol, Providers: []string{ "1", "2", @@ -174,7 +174,7 @@ func TestValidateCurrencyPairProviders(t *testing.T) { CurrencyPairProvidersList{ CurrencyPairProviders{ BaseDenom: OjoDenom, - QuoteDenom: USDDenom, + QuoteDenom: USDSymbol, }, }, ) @@ -184,7 +184,7 @@ func TestValidateCurrencyPairProviders(t *testing.T) { CurrencyPairProvidersList{ CurrencyPairProviders{ BaseDenom: OjoDenom, - QuoteDenom: USDDenom, + QuoteDenom: USDSymbol, Providers: []string{ "1", "2", @@ -302,5 +302,11 @@ func TestParamsEqual(t *testing.T) { func TestAddDefaultRB(t *testing.T) { p := DefaultRewardBands() p.AddDefault("foo") - require.Equal(t, p.String(), "symbol_denom: OJO\nreward_band: \"0.020000000000000000\"\n\nsymbol_denom: ATOM\nreward_band: \"0.020000000000000000\"\n\nsymbol_denom: foo\nreward_band: \"0.020000000000000000\"") + require.Equal(t, p.String(), + "symbol_denom: OJO\nreward_band: \"0.020000000000000000\"\n\n"+ + "symbol_denom: ATOM\nreward_band: \"0.020000000000000000\"\n\n"+ + "symbol_denom: USDT\nreward_band: \"0.020000000000000000\"\n\n"+ + "symbol_denom: BTC\nreward_band: \"0.020000000000000000\"\n\n"+ + "symbol_denom: ETH\nreward_band: \"0.020000000000000000\"\n\n"+ + "symbol_denom: foo\nreward_band: \"0.020000000000000000\"") } From 128313a2ff1582559c2e5ffea337bb54172bdb1a Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 15:15:40 -0600 Subject: [PATCH 25/27] README update --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index aae67f9f..e052d2f7 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,14 @@ To install the `ojod` binary: $ make install ``` +## Run Node + +Example command structure for running a node with a price feeder config file located at `./price-feeder.example.config` (See [price-feeder](https://github.com/ojo-network/price-feeder) repo for more information on configuring an Ojo price feeder) + +``` +$ ojod start --pricefeeder.config_path=./price-feeder.example.config --pricefeeder.log_level="INFO" --pricefeeder.chain_config=TRUE --pricefeeder.oracle_tick_time=5s +``` + ## Networks Ojo currently has three active public networks: From 3726583b605fd2c9636477c2b92d06f84d0cf1d1 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 15:51:30 -0600 Subject: [PATCH 26/27] super lint --- README.md | 2 +- pricefeeder/config.go | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e052d2f7..d28f856e 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ $ make install Example command structure for running a node with a price feeder config file located at `./price-feeder.example.config` (See [price-feeder](https://github.com/ojo-network/price-feeder) repo for more information on configuring an Ojo price feeder) -``` +```shell $ ojod start --pricefeeder.config_path=./price-feeder.example.config --pricefeeder.log_level="INFO" --pricefeeder.chain_config=TRUE --pricefeeder.oracle_tick_time=5s ``` diff --git a/pricefeeder/config.go b/pricefeeder/config.go index b02b3783..e9b0ac72 100644 --- a/pricefeeder/config.go +++ b/pricefeeder/config.go @@ -11,14 +11,16 @@ import ( const ( DefaultConfigTemplate = ` [pricefeeder] -# Path to price feeder config file +# Path to price feeder config file. config_path = "" -# Specifies whether the currency pair providers and currency deviation threshold values should -# be read from the oracle module's on chain parameters or the price feeder config + +# Specifies whether to use the on chain price feeder provider pair and deviation threshold values or the config file. chain_config = true -# Log level of price feeder process + +# Log level of price feeder process. log_level = "info" -# Time interval that the price feeder's oracle process waits before fetching for new prices + +# Time interval that the price feeder's oracle process waits before fetching for new prices. oracle_tick_time = "5s" ` ) From ed7a984c26cb93513f54149449c4d130b3cc9496 Mon Sep 17 00:00:00 2001 From: rbajollari Date: Tue, 9 Apr 2024 15:54:32 -0600 Subject: [PATCH 27/27] go mod tidy --- go.mod | 2 ++ go.sum | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/go.mod b/go.mod index 0ff535b7..96323b95 100644 --- a/go.mod +++ b/go.mod @@ -139,7 +139,9 @@ require ( github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/docker/cli v24.0.2+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker v24.0.9+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect diff --git a/go.sum b/go.sum index 56801572..4e1fcd36 100644 --- a/go.sum +++ b/go.sum @@ -486,8 +486,12 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM= github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=