From 351b21dec4abdab8cf90e2e20c896ed0beb4d7d8 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Mon, 15 Aug 2022 19:02:46 +0800 Subject: [PATCH 01/15] add: wire oracle --- app/app.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/app/app.go b/app/app.go index 345c7850c..3bf55b099 100644 --- a/app/app.go +++ b/app/app.go @@ -3,6 +3,9 @@ package app import ( "encoding/json" "fmt" + "github.com/NibiruChain/nibiru/x/oracle" + oraclekeeper "github.com/NibiruChain/nibiru/x/oracle/keeper" + oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" "io" "net/http" "os" @@ -178,6 +181,7 @@ var ( epochs.AppModuleBasic{}, stablecoin.AppModuleBasic{}, perp.AppModuleBasic{}, + oracle.AppModuleBasic{}, lockup.AppModuleBasic{}, incentivization.AppModuleBasic{}, vpool.AppModuleBasic{}, @@ -199,6 +203,7 @@ var ( perptypes.PerpEFModuleAccount: {}, perptypes.FeePoolModuleAccount: {}, epochstypes.ModuleName: {}, + oracletypes.ModuleName: nil, lockuptypes.ModuleName: {authtypes.Minter, authtypes.Burner}, stablecointypes.StableEFModuleAccount: {authtypes.Burner}, common.TreasuryPoolModuleAccount: {}, @@ -268,6 +273,7 @@ type NibiruApp struct { // --------------- // Nibiru keepers // --------------- + OracleKeeper oraclekeeper.Keeper DexKeeper dexkeeper.Keeper StablecoinKeeper stablecoinkeeper.Keeper PerpKeeper perpkeeper.Keeper @@ -331,6 +337,7 @@ func NewNibiruApp( ibchost.StoreKey, ibctransfertypes.StoreKey, // nibiru x/ keys + oracletypes.StoreKey, dextypes.StoreKey, pricefeedtypes.StoreKey, stablecointypes.StoreKey, @@ -422,6 +429,14 @@ func NewNibiruApp( // ---------------------------------- Nibiru Chain x/ keepers + app.OracleKeeper = oraclekeeper.NewKeeper( + appCodec, + keys[oracletypes.StoreKey], + app.GetSubspace(oracletypes.ModuleName), + app.AccountKeeper, app.BankKeeper, app.DistrKeeper, &stakingKeeper, + distrtypes.ModuleName, + ) + app.DexKeeper = dexkeeper.NewKeeper( appCodec, keys[dextypes.StoreKey], app.GetSubspace(dextypes.ModuleName), app.AccountKeeper, app.BankKeeper, app.DistrKeeper) @@ -533,6 +548,9 @@ func NewNibiruApp( var skipGenesisInvariants = cast.ToBool( appOpts.Get(crisis.FlagSkipGenesisInvariants)) + oracleModule := oracle.NewAppModule( + appCodec, app.OracleKeeper, app.AccountKeeper, app.BankKeeper) + dexModule := dex.NewAppModule( appCodec, app.DexKeeper, app.AccountKeeper, app.BankKeeper) pricefeedModule := pricefeed.NewAppModule( @@ -574,6 +592,7 @@ func NewNibiruApp( params.NewAppModule(app.ParamsKeeper), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), // native x/ + oracleModule, dexModule, pricefeedModule, stablecoinModule, @@ -619,6 +638,7 @@ func NewNibiruApp( perptypes.ModuleName, lockuptypes.ModuleName, incentivizationtypes.ModuleName, + oracletypes.ModuleName, // ibc modules ibchost.ModuleName, ibctransfertypes.ModuleName, @@ -626,6 +646,7 @@ func NewNibiruApp( app.mm.SetOrderEndBlockers( crisistypes.ModuleName, govtypes.ModuleName, + oracletypes.ModuleName, stakingtypes.ModuleName, capabilitytypes.ModuleName, authtypes.ModuleName, @@ -677,6 +698,7 @@ func NewNibiruApp( upgradetypes.ModuleName, vestingtypes.ModuleName, // native x/ + oracletypes.ModuleName, dextypes.ModuleName, pricefeedtypes.ModuleName, epochstypes.ModuleName, @@ -990,6 +1012,7 @@ func initParamsKeeper( paramsKeeper.Subspace(pricefeedtypes.ModuleName) paramsKeeper.Subspace(epochstypes.ModuleName) paramsKeeper.Subspace(stablecointypes.ModuleName) + paramsKeeper.Subspace(oracletypes.ModuleName) // ibc params keepers paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) From 580513858bb85e7d41daaf32d25b7c5ce702a07b Mon Sep 17 00:00:00 2001 From: godismercilex Date: Mon, 15 Aug 2022 19:02:58 +0800 Subject: [PATCH 02/15] temp: attempt to fix localnet.sh --- scripts/localnet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/localnet.sh b/scripts/localnet.sh index 8ca2c2ee6..28a8da373 100755 --- a/scripts/localnet.sh +++ b/scripts/localnet.sh @@ -1,5 +1,5 @@ #!/bin/sh -#set -e +set -e # Console log text colour red=`tput setaf 9` From 9ef8aa67d7a89722cfd88902c9f431d66164b02c Mon Sep 17 00:00:00 2001 From: Agent Smith Date: Mon, 15 Aug 2022 13:05:40 +0200 Subject: [PATCH 03/15] upgrade changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 660aa1b68..42cfe4a17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,7 +44,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### CI -* [#795](https://github.com/NibiruChain/nibiru/pull/795) Integration tests run when PR is approved +* [#795](https://github.com/NibiruChain/nibiru/pull/795) - integration tests run when PR is approved +* [#826](https://github.com/NibiruChain/nibiru/pull/826) - create and push docker image on release ### Improvements From 730331753ceabf0d6fd4011dd565da968390c7fd Mon Sep 17 00:00:00 2001 From: godismercilex Date: Mon, 15 Aug 2022 19:07:20 +0800 Subject: [PATCH 04/15] add: slash logging --- x/oracle/keeper/slash.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/oracle/keeper/slash.go b/x/oracle/keeper/slash.go index 55ea85796..af673a4bd 100644 --- a/x/oracle/keeper/slash.go +++ b/x/oracle/keeper/slash.go @@ -38,6 +38,7 @@ func (k Keeper) SlashAndResetMissCounters(ctx sdk.Context) { ctx, consAddr, distributionHeight, validator.GetConsensusPower(powerReduction), slashFraction, ) + k.Logger(ctx).Info("slash", "validator", consAddr.String(), "fraction", slashFraction.String()) k.StakingKeeper.Jail(ctx, consAddr) } } From e4288f0e2df61a4c9351e7d50751d0e0cbee9e08 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Mon, 15 Aug 2022 19:27:08 +0800 Subject: [PATCH 05/15] add: miss counters logging --- x/oracle/abci.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/oracle/abci.go b/x/oracle/abci.go index a6076f465..42ef65c36 100644 --- a/x/oracle/abci.go +++ b/x/oracle/abci.go @@ -16,6 +16,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) { params := k.GetParams(ctx) if types.IsPeriodLastBlock(ctx, params.VotePeriod) { + k.Logger(ctx).Info("processing validator price votes") // Build claim map over all validators in active set validatorClaimMap := make(map[string]types.Claim) @@ -91,6 +92,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) { // Increase miss counter k.SetMissCounter(ctx, claim.Recipient, k.GetMissCounter(ctx, claim.Recipient)+1) + k.Logger(ctx).Info("vote miss", "validator", claim.Recipient.String()) } // Distribute rewards to ballot winners From b2dc992d3ddc676aee4dd51c29d756d21d38e813 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Tue, 16 Aug 2022 19:52:19 +0800 Subject: [PATCH 06/15] tmp --- x/oracle/app_test.go | 133 +++++++++++++++++++++++++++++++++++++++++++ x/testutil/cli/tx.go | 36 ++++++++++++ 2 files changed, 169 insertions(+) create mode 100644 x/oracle/app_test.go diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go new file mode 100644 index 000000000..008d5b6a9 --- /dev/null +++ b/x/oracle/app_test.go @@ -0,0 +1,133 @@ +package oracle_test + +import ( + "context" + "github.com/NibiruChain/nibiru/app" + oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" + testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" + "github.com/NibiruChain/nibiru/x/testutil/testapp" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "log" + "testing" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg testutilcli.Config + network *testutilcli.Network +} + +func (s *IntegrationTestSuite) SetupTest() { + app.SetPrefixes(app.AccountAddressPrefix) + s.cfg = testutilcli.BuildNetworkConfig(testapp.NewTestGenesisStateFromDefault()) + s.cfg.NumValidators = 3 + s.cfg.GenesisState[oracletypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(func() codec.ProtoMarshaler { + gs := oracletypes.DefaultGenesisState() + gs.Params.Whitelist = oracletypes.PairList{ + oracletypes.Pair{Name: "unibi:usdc"}, + } + + return gs + }()) + + s.network = testutilcli.NewNetwork(s.T(), s.cfg) + _, err := s.network.WaitForHeight(2) + require.NoError(s.T(), err) +} + +func (s *IntegrationTestSuite) TestSuccessfulVoting() { + prices := []map[string]sdk.Dec{ + { + "unibi:usdc": sdk.MustNewDecFromStr("1"), + }, + { + "unibi:usdc": sdk.MustNewDecFromStr("1"), + }, + { + "unibi:usdc": sdk.MustNewDecFromStr("1"), + }, + } + votes := s.sendPrevotes(prices) + + s.waitRevealVotePeriod() + + s.sendVotes(votes) + + gotPrices := s.prices() + + require.Equal(s.T(), prices, gotPrices) +} + +func (s *IntegrationTestSuite) sendPrevotes(prices []map[string]sdk.Dec) []string { + strVotes := make([]string, len(prices)) + for i, val := range s.network.Validators { + log.Printf("%s", val.Address.String()) + raw := prices[i] + votes := make(oracletypes.ExchangeRateTuples, 0, len(raw)) + for pair, price := range raw { + votes = append(votes, oracletypes.NewExchangeRateTuple(pair, price)) + } + + pricesStr, err := votes.ToString() + require.NoError(s.T(), err) + _, err = s.network.SendTx(val.Address, &oracletypes.MsgAggregateExchangeRatePrevote{ + Hash: oracletypes.GetAggregateVoteHash("1", pricesStr, val.ValAddress).String(), + Feeder: val.Address.String(), + Validator: val.ValAddress.String(), + }) + require.NoError(s.T(), err) + + strVotes[i] = pricesStr + } + + return strVotes +} + +func (s *IntegrationTestSuite) sendVotes(rates []string) { + for i, val := range s.network.Validators { + _, err := s.network.SendTx(val.Address, &oracletypes.MsgAggregateExchangeRateVote{ + Salt: "1", + ExchangeRates: rates[i], + Feeder: val.Address.String(), + Validator: val.ValAddress.String(), + }) + require.NoError(s.T(), err) + } +} + +func (s *IntegrationTestSuite) waitRevealVotePeriod() { + + params, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).Params(context.Background(), &oracletypes.QueryParamsRequest{}) + require.NoError(s.T(), err) + + votePeriod := params.Params.VotePeriod + + height, err := s.network.LatestHeight() + require.NoError(s.T(), err) + + waitBlock := uint64(height)/votePeriod + votePeriod + + _, err = s.network.WaitForHeight(int64(waitBlock + 1)) + require.NoError(s.T(), err) +} + +func (s *IntegrationTestSuite) prices() map[string]sdk.Dec { + rawRates, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).ExchangeRates(context.Background(), &oracletypes.QueryExchangeRatesRequest{}) + require.NoError(s.T(), err) + + prices := make(map[string]sdk.Dec) + + for _, p := range rawRates.ExchangeRates { + prices[p.Pair] = p.ExchangeRate + } + + return prices +} + +func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) +} diff --git a/x/testutil/cli/tx.go b/x/testutil/cli/tx.go index e82aae86b..045086c00 100644 --- a/x/testutil/cli/tx.go +++ b/x/testutil/cli/tx.go @@ -1,7 +1,10 @@ package cli import ( + "context" "fmt" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/testutil/cli" @@ -96,3 +99,36 @@ func ExecTx(network *Network, cmd *cobra.Command, txSender sdk.AccAddress, args return resp, nil } + +func (n *Network) SendTx(addr sdk.AccAddress, msgs ...sdk.Msg) (*sdk.TxResponse, error) { + cfg := n.Config + kb := n.Validators[0].ClientCtx.Keyring + info, err := kb.KeyByAddress(addr) + require.NoError(n.T, err) + rpc := n.Validators[0].RPCClient + txBuilder := cfg.TxConfig.NewTxBuilder() + require.NoError(n.T, txBuilder.SetMsgs(msgs...)) + txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, sdk.NewInt(1)))) + txBuilder.SetGasLimit(1000000) + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(cfg.ChainID). + WithKeybase(kb). + WithTxConfig(cfg.TxConfig). + WithAccountRetriever(cfg.AccountRetriever) + + err = tx.Sign(txFactory, info.GetName(), txBuilder, true) + require.NoError(n.T, err) + + txBytes, err := cfg.TxConfig.TxEncoder()(txBuilder.GetTx()) + require.NoError(n.T, err) + + respRaw, err := rpc.BroadcastTxCommit(context.Background(), txBytes) + require.NoError(n.T, err) + + require.Truef(n.T, respRaw.CheckTx.IsOK(), "tx failed: %s", respRaw.CheckTx.Log) + require.Truef(n.T, respRaw.DeliverTx.IsOK(), "tx failed: %s", respRaw.CheckTx.Log) + + return sdk.NewResponseFormatBroadcastTxCommit(respRaw), nil +} From 4a51b7fd401dc35c2de5520253dd6c827d8a1b8f Mon Sep 17 00:00:00 2001 From: godismercilex Date: Tue, 16 Aug 2022 20:43:30 +0800 Subject: [PATCH 07/15] fix: almost there.... --- x/oracle/app_test.go | 4 ++-- x/oracle/keeper/msg_server.go | 5 ++++- x/testutil/cli/tx.go | 14 +++++++++----- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go index 008d5b6a9..7bfae2da3 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/app_test.go @@ -24,7 +24,7 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupTest() { app.SetPrefixes(app.AccountAddressPrefix) s.cfg = testutilcli.BuildNetworkConfig(testapp.NewTestGenesisStateFromDefault()) - s.cfg.NumValidators = 3 + s.cfg.NumValidators = 1 s.cfg.GenesisState[oracletypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(func() codec.ProtoMarshaler { gs := oracletypes.DefaultGenesisState() gs.Params.Whitelist = oracletypes.PairList{ @@ -109,7 +109,7 @@ func (s *IntegrationTestSuite) waitRevealVotePeriod() { height, err := s.network.LatestHeight() require.NoError(s.T(), err) - waitBlock := uint64(height)/votePeriod + votePeriod + waitBlock := (uint64(height)/votePeriod)*votePeriod + votePeriod _, err = s.network.WaitForHeight(int64(waitBlock + 1)) require.NoError(s.T(), err) diff --git a/x/oracle/keeper/msg_server.go b/x/oracle/keeper/msg_server.go index 95a118bc1..3d8673669 100644 --- a/x/oracle/keeper/msg_server.go +++ b/x/oracle/keeper/msg_server.go @@ -90,7 +90,10 @@ func (ms msgServer) AggregateExchangeRateVote(goCtx context.Context, msg *types. // Check a msg is submitted proper period if (uint64(ctx.BlockHeight())/params.VotePeriod)-(aggregatePrevote.SubmitBlock/params.VotePeriod) != 1 { - return nil, types.ErrRevealPeriodMissMatch + return nil, types.ErrRevealPeriodMissMatch.Wrapf( + "aggregate prevote block: %d, current block: %d, vote period: %d", + aggregatePrevote.SubmitBlock, ctx.BlockHeight(), params.VotePeriod, + ) } exchangeRateTuples, err := types.ParseExchangeRateTuples(msg.ExchangeRates) diff --git a/x/testutil/cli/tx.go b/x/testutil/cli/tx.go index 045086c00..7d083336f 100644 --- a/x/testutil/cli/tx.go +++ b/x/testutil/cli/tx.go @@ -3,13 +3,12 @@ package cli import ( "context" "fmt" - "github.com/cosmos/cosmos-sdk/client/tx" - "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/testutil/cli" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" + "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/abci/types" "github.com/NibiruChain/nibiru/x/common" @@ -111,12 +110,17 @@ func (n *Network) SendTx(addr sdk.AccAddress, msgs ...sdk.Msg) (*sdk.TxResponse, txBuilder.SetFeeAmount(sdk.NewCoins(sdk.NewCoin(cfg.BondDenom, sdk.NewInt(1)))) txBuilder.SetGasLimit(1000000) + acc, err := cfg.AccountRetriever.GetAccount(n.Validators[0].ClientCtx, addr) + require.NoError(n.T, err) + txFactory := tx.Factory{} txFactory = txFactory. WithChainID(cfg.ChainID). WithKeybase(kb). WithTxConfig(cfg.TxConfig). - WithAccountRetriever(cfg.AccountRetriever) + WithAccountRetriever(cfg.AccountRetriever). + WithAccountNumber(acc.GetAccountNumber()). + WithSequence(acc.GetSequence()) err = tx.Sign(txFactory, info.GetName(), txBuilder, true) require.NoError(n.T, err) @@ -128,7 +132,7 @@ func (n *Network) SendTx(addr sdk.AccAddress, msgs ...sdk.Msg) (*sdk.TxResponse, require.NoError(n.T, err) require.Truef(n.T, respRaw.CheckTx.IsOK(), "tx failed: %s", respRaw.CheckTx.Log) - require.Truef(n.T, respRaw.DeliverTx.IsOK(), "tx failed: %s", respRaw.CheckTx.Log) + require.Truef(n.T, respRaw.DeliverTx.IsOK(), "tx failed: %s", respRaw.DeliverTx.Log) return sdk.NewResponseFormatBroadcastTxCommit(respRaw), nil } From 02e591e94d329f08bdc55f6d1f6c2d236354b65e Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 17:35:25 +0800 Subject: [PATCH 08/15] add: finalize first oracle scenario integration test --- x/oracle/app_test.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go index 7bfae2da3..7d3f04997 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/app_test.go @@ -10,7 +10,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "log" "testing" ) @@ -53,19 +52,19 @@ func (s *IntegrationTestSuite) TestSuccessfulVoting() { } votes := s.sendPrevotes(prices) - s.waitRevealVotePeriod() + s.waitVoteRevealBlock() s.sendVotes(votes) - gotPrices := s.prices() + s.waitPriceUpdateBlock() - require.Equal(s.T(), prices, gotPrices) + gotPrices := s.currentPrices() + require.Equal(s.T(), map[string]sdk.Dec{"unibi:usdc": sdk.MustNewDecFromStr("1")}, gotPrices) } func (s *IntegrationTestSuite) sendPrevotes(prices []map[string]sdk.Dec) []string { strVotes := make([]string, len(prices)) for i, val := range s.network.Validators { - log.Printf("%s", val.Address.String()) raw := prices[i] votes := make(oracletypes.ExchangeRateTuples, 0, len(raw)) for pair, price := range raw { @@ -99,7 +98,7 @@ func (s *IntegrationTestSuite) sendVotes(rates []string) { } } -func (s *IntegrationTestSuite) waitRevealVotePeriod() { +func (s *IntegrationTestSuite) waitVoteRevealBlock() { params, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).Params(context.Background(), &oracletypes.QueryParamsRequest{}) require.NoError(s.T(), err) @@ -115,7 +114,22 @@ func (s *IntegrationTestSuite) waitRevealVotePeriod() { require.NoError(s.T(), err) } -func (s *IntegrationTestSuite) prices() map[string]sdk.Dec { +func (s *IntegrationTestSuite) waitPriceUpdateBlock() { + params, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).Params(context.Background(), &oracletypes.QueryParamsRequest{}) + require.NoError(s.T(), err) + + votePeriod := params.Params.VotePeriod + + height, err := s.network.LatestHeight() + require.NoError(s.T(), err) + + waitBlock := (uint64(height)/votePeriod)*votePeriod + votePeriod + + _, err = s.network.WaitForHeight(int64(waitBlock + 1)) + require.NoError(s.T(), err) +} + +func (s *IntegrationTestSuite) currentPrices() map[string]sdk.Dec { rawRates, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).ExchangeRates(context.Background(), &oracletypes.QueryExchangeRatesRequest{}) require.NoError(s.T(), err) From 327e6cd8b39ccf8b0cbd6cf563d35de13d68c0a2 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 17:39:49 +0800 Subject: [PATCH 09/15] add: function to find private key info for an address --- x/testutil/cli/network.go | 12 ++++++++++++ x/testutil/cli/tx.go | 4 +--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/x/testutil/cli/network.go b/x/testutil/cli/network.go index 0f027dcd8..3853d20db 100644 --- a/x/testutil/cli/network.go +++ b/x/testutil/cli/network.go @@ -517,3 +517,15 @@ func (n *Network) Cleanup() { n.T.Log("finished cleaning up test network") } + +func (n *Network) keyBaseAndInfoForAddr(addr sdk.AccAddress) (keyring.Keyring, keyring.Info) { + for _, v := range n.Validators { + info, err := v.ClientCtx.Keyring.KeyByAddress(addr) + if err == nil { + return v.ClientCtx.Keyring, info + } + } + + n.T.Fatalf("address not found in any of the known validators keyrings: %s", addr.String()) + return nil, nil +} diff --git a/x/testutil/cli/tx.go b/x/testutil/cli/tx.go index 7d083336f..bc07dad00 100644 --- a/x/testutil/cli/tx.go +++ b/x/testutil/cli/tx.go @@ -101,9 +101,7 @@ func ExecTx(network *Network, cmd *cobra.Command, txSender sdk.AccAddress, args func (n *Network) SendTx(addr sdk.AccAddress, msgs ...sdk.Msg) (*sdk.TxResponse, error) { cfg := n.Config - kb := n.Validators[0].ClientCtx.Keyring - info, err := kb.KeyByAddress(addr) - require.NoError(n.T, err) + kb, info := n.keyBaseAndInfoForAddr(addr) rpc := n.Validators[0].RPCClient txBuilder := cfg.TxConfig.NewTxBuilder() require.NoError(n.T, txBuilder.SetMsgs(msgs...)) From 746091ad31e7989e0cadedbcb9d81026723acc12 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 18:35:09 +0800 Subject: [PATCH 10/15] fix: test --- x/oracle/app_test.go | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go index 7d3f04997..5b78aa2b0 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/app_test.go @@ -23,11 +23,12 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupTest() { app.SetPrefixes(app.AccountAddressPrefix) s.cfg = testutilcli.BuildNetworkConfig(testapp.NewTestGenesisStateFromDefault()) - s.cfg.NumValidators = 1 + s.cfg.NumValidators = 4 s.cfg.GenesisState[oracletypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(func() codec.ProtoMarshaler { gs := oracletypes.DefaultGenesisState() gs.Params.Whitelist = oracletypes.PairList{ - oracletypes.Pair{Name: "unibi:usdc"}, + oracletypes.Pair{Name: "nibi:usdc"}, + oracletypes.Pair{Name: "btc:usdc"}, } return gs @@ -39,15 +40,30 @@ func (s *IntegrationTestSuite) SetupTest() { } func (s *IntegrationTestSuite) TestSuccessfulVoting() { + // assuming validators have equal power + // we use the weighted median. + // what happens is that prices are ordered + // based on exchange rate, from lowest to highest. + // then the median is picked, based on consensus power + // so obviously, in this case, since validators have the same power + // once weight (based on power) >= total power (sum of weights) + // then the number picked is the one in the middle always. prices := []map[string]sdk.Dec{ { - "unibi:usdc": sdk.MustNewDecFromStr("1"), + "nibi:usdc": sdk.MustNewDecFromStr("1"), + "btc:usdc": sdk.MustNewDecFromStr("100203.0"), }, { - "unibi:usdc": sdk.MustNewDecFromStr("1"), + "nibi:usdc": sdk.MustNewDecFromStr("1"), + "btc:usdc": sdk.MustNewDecFromStr("100150.5"), }, { - "unibi:usdc": sdk.MustNewDecFromStr("1"), + "nibi:usdc": sdk.MustNewDecFromStr("1"), + "btc:usdc": sdk.MustNewDecFromStr("100200.9"), + }, + { + "nibi:usdc": sdk.MustNewDecFromStr("1"), + "btc:usdc": sdk.MustNewDecFromStr("100300.9"), }, } votes := s.sendPrevotes(prices) @@ -59,7 +75,13 @@ func (s *IntegrationTestSuite) TestSuccessfulVoting() { s.waitPriceUpdateBlock() gotPrices := s.currentPrices() - require.Equal(s.T(), map[string]sdk.Dec{"unibi:usdc": sdk.MustNewDecFromStr("1")}, gotPrices) + require.Equal(s.T(), + map[string]sdk.Dec{ + "nibi:usdc": sdk.MustNewDecFromStr("1"), + "btc:usdc": sdk.MustNewDecFromStr("100200.9"), + }, + gotPrices, + ) } func (s *IntegrationTestSuite) sendPrevotes(prices []map[string]sdk.Dec) []string { From 7b63943170af3df3c02975174825831d4df5c99d Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 19:06:57 +0800 Subject: [PATCH 11/15] chore: move oracle to simapp --- simapp/app.go | 23 +++++++++++++++++++++++ x/oracle/app_test.go | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index dd8af2422..ea61dc2f3 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -3,11 +3,14 @@ package simapp import ( "encoding/json" "fmt" + "github.com/NibiruChain/nibiru/x/oracle" + oraclekeeper "github.com/NibiruChain/nibiru/x/oracle/keeper" "io" "net/http" "os" "path/filepath" + oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" _ "github.com/cosmos/cosmos-sdk/client/docs/statik" @@ -174,6 +177,7 @@ var ( ibctransfer.AppModuleBasic{}, // native x/ + oracle.AppModuleBasic{}, dex.AppModuleBasic{}, pricefeed.AppModuleBasic{}, epochs.AppModuleBasic{}, @@ -201,6 +205,7 @@ var ( perptypes.FeePoolModuleAccount: {}, epochstypes.ModuleName: {}, lockuptypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + oracletypes.ModuleName: nil, stablecointypes.StableEFModuleAccount: {authtypes.Burner}, common.TreasuryPoolModuleAccount: {}, } @@ -269,6 +274,7 @@ type NibiruTestApp struct { // --------------- // Nibiru keepers // --------------- + OracleKeeper oraclekeeper.Keeper DexKeeper dexkeeper.Keeper StablecoinKeeper stablecoinkeeper.Keeper PerpKeeper perpkeeper.Keeper @@ -332,6 +338,7 @@ func NewNibiruTestApp( ibchost.StoreKey, ibctransfertypes.StoreKey, // nibiru x/ keys + oracletypes.StoreKey, dextypes.StoreKey, pricefeedtypes.StoreKey, stablecointypes.StoreKey, @@ -423,6 +430,14 @@ func NewNibiruTestApp( // ---------------------------------- Nibiru Chain x/ keepers + app.OracleKeeper = oraclekeeper.NewKeeper( + appCodec, + keys[oracletypes.StoreKey], + app.GetSubspace(oracletypes.ModuleName), + app.AccountKeeper, app.BankKeeper, app.DistrKeeper, &stakingKeeper, + distrtypes.ModuleName, + ) + app.DexKeeper = dexkeeper.NewKeeper( appCodec, keys[dextypes.StoreKey], app.GetSubspace(dextypes.ModuleName), app.AccountKeeper, app.BankKeeper, app.DistrKeeper) @@ -534,6 +549,9 @@ func NewNibiruTestApp( var skipGenesisInvariants = cast.ToBool( appOpts.Get(crisis.FlagSkipGenesisInvariants)) + oracleModule := oracle.NewAppModule( + appCodec, app.OracleKeeper, app.AccountKeeper, app.BankKeeper) + dexModule := dex.NewAppModule( appCodec, app.DexKeeper, app.AccountKeeper, app.BankKeeper) pricefeedModule := pricefeed.NewAppModule( @@ -575,6 +593,7 @@ func NewNibiruTestApp( params.NewAppModule(app.ParamsKeeper), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), // native x/ + oracleModule, dexModule, pricefeedModule, stablecoinModule, @@ -620,6 +639,7 @@ func NewNibiruTestApp( perptypes.ModuleName, lockuptypes.ModuleName, incentivizationtypes.ModuleName, + oracletypes.ModuleName, // ibc modules ibchost.ModuleName, ibctransfertypes.ModuleName, @@ -627,6 +647,7 @@ func NewNibiruTestApp( app.mm.SetOrderEndBlockers( crisistypes.ModuleName, govtypes.ModuleName, + oracletypes.ModuleName, stakingtypes.ModuleName, capabilitytypes.ModuleName, authtypes.ModuleName, @@ -678,6 +699,7 @@ func NewNibiruTestApp( upgradetypes.ModuleName, vestingtypes.ModuleName, // native x/ + oracletypes.ModuleName, dextypes.ModuleName, pricefeedtypes.ModuleName, epochstypes.ModuleName, @@ -992,6 +1014,7 @@ func initParamsKeeper( paramsKeeper.Subspace(pricefeedtypes.ModuleName) paramsKeeper.Subspace(epochstypes.ModuleName) paramsKeeper.Subspace(stablecointypes.ModuleName) + paramsKeeper.Subspace(oracletypes.ModuleName) // ibc params keepers paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go index 5b78aa2b0..0810f301f 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/app_test.go @@ -3,9 +3,9 @@ package oracle_test import ( "context" "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/simapp" oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" - "github.com/NibiruChain/nibiru/x/testutil/testapp" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" @@ -22,7 +22,7 @@ type IntegrationTestSuite struct { func (s *IntegrationTestSuite) SetupTest() { app.SetPrefixes(app.AccountAddressPrefix) - s.cfg = testutilcli.BuildNetworkConfig(testapp.NewTestGenesisStateFromDefault()) + s.cfg = testutilcli.BuildNetworkConfig(simapp.NewTestGenesisStateFromDefault()) s.cfg.NumValidators = 4 s.cfg.GenesisState[oracletypes.ModuleName] = s.cfg.Codec.MustMarshalJSON(func() codec.ProtoMarshaler { gs := oracletypes.DefaultGenesisState() From 97ac4b9e6649ff0b712cf8e24a458e65b8a43071 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 19:08:03 +0800 Subject: [PATCH 12/15] chore: lint --- simapp/app.go | 8 +++++--- x/oracle/app_test.go | 13 +++++++------ x/testutil/cli/tx.go | 1 + 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/simapp/app.go b/simapp/app.go index ea61dc2f3..e8949d76e 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -3,14 +3,14 @@ package simapp import ( "encoding/json" "fmt" - "github.com/NibiruChain/nibiru/x/oracle" - oraclekeeper "github.com/NibiruChain/nibiru/x/oracle/keeper" "io" "net/http" "os" "path/filepath" - oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" + "github.com/NibiruChain/nibiru/x/oracle" + oraclekeeper "github.com/NibiruChain/nibiru/x/oracle/keeper" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" _ "github.com/cosmos/cosmos-sdk/client/docs/statik" @@ -101,6 +101,8 @@ import ( tmos "github.com/tendermint/tendermint/libs/os" dbm "github.com/tendermint/tm-db" + oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" + nibiapp "github.com/NibiruChain/nibiru/app" "github.com/NibiruChain/nibiru/x/common" "github.com/NibiruChain/nibiru/x/dex" diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go index 0810f301f..dd90b85b9 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/app_test.go @@ -2,15 +2,17 @@ package oracle_test import ( "context" - "github.com/NibiruChain/nibiru/app" - "github.com/NibiruChain/nibiru/simapp" - oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" - testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" + "testing" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - "testing" + + "github.com/NibiruChain/nibiru/app" + "github.com/NibiruChain/nibiru/simapp" + oracletypes "github.com/NibiruChain/nibiru/x/oracle/types" + testutilcli "github.com/NibiruChain/nibiru/x/testutil/cli" ) type IntegrationTestSuite struct { @@ -121,7 +123,6 @@ func (s *IntegrationTestSuite) sendVotes(rates []string) { } func (s *IntegrationTestSuite) waitVoteRevealBlock() { - params, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).Params(context.Background(), &oracletypes.QueryParamsRequest{}) require.NoError(s.T(), err) diff --git a/x/testutil/cli/tx.go b/x/testutil/cli/tx.go index bc07dad00..8292d58c3 100644 --- a/x/testutil/cli/tx.go +++ b/x/testutil/cli/tx.go @@ -3,6 +3,7 @@ package cli import ( "context" "fmt" + "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" "github.com/cosmos/cosmos-sdk/testutil/cli" From 829ced94763782fd4eda3ee7a8c427828278bdd8 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 19:09:54 +0800 Subject: [PATCH 13/15] chore: docs and function simplification --- x/oracle/app_test.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/x/oracle/app_test.go b/x/oracle/app_test.go index dd90b85b9..3733af4f2 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/app_test.go @@ -137,19 +137,9 @@ func (s *IntegrationTestSuite) waitVoteRevealBlock() { require.NoError(s.T(), err) } +// it's an alias, but it exists to give better understanding of what we're doing in test cases scenarios func (s *IntegrationTestSuite) waitPriceUpdateBlock() { - params, err := oracletypes.NewQueryClient(s.network.Validators[0].ClientCtx).Params(context.Background(), &oracletypes.QueryParamsRequest{}) - require.NoError(s.T(), err) - - votePeriod := params.Params.VotePeriod - - height, err := s.network.LatestHeight() - require.NoError(s.T(), err) - - waitBlock := (uint64(height)/votePeriod)*votePeriod + votePeriod - - _, err = s.network.WaitForHeight(int64(waitBlock + 1)) - require.NoError(s.T(), err) + s.waitVoteRevealBlock() } func (s *IntegrationTestSuite) currentPrices() map[string]sdk.Dec { From 14cdc9b247ccc7abeb89c3d483e008c1fd63ce45 Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 19:11:14 +0800 Subject: [PATCH 14/15] chore: CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e640b91..9e7f9d196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * [#813](https://github.com/NibiruChain/nibiru/pull/813) - (vpool): Expose mark price, mark TWAP, index price, and k (swap invariant) in the all-pools query * [#816](https://github.com/NibiruChain/nibiru/pull/816) - Remove tobin tax from x/oracle * [#810](https://github.com/NibiruChain/nibiru/pull/810) - feat(x/perp): expose 'marginRatioIndex' and block number on QueryTraderPosition +* [#832](https://github.com/NibiruChain/nibiru/pull/832) - x/oracle app wiring ### Documentation From 632501e69f04846ad4e07d7464a3c1cc029be66f Mon Sep 17 00:00:00 2001 From: godismercilex Date: Wed, 17 Aug 2022 23:44:56 +0800 Subject: [PATCH 15/15] temp: move app_test.go to a separate pkg --- x/oracle/{ => integration_test}/app_test.go | 2 +- x/oracle/keeper/test_utils.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename x/oracle/{ => integration_test}/app_test.go (99%) diff --git a/x/oracle/app_test.go b/x/oracle/integration_test/app_test.go similarity index 99% rename from x/oracle/app_test.go rename to x/oracle/integration_test/app_test.go index 3733af4f2..3e9d12e05 100644 --- a/x/oracle/app_test.go +++ b/x/oracle/integration_test/app_test.go @@ -1,4 +1,4 @@ -package oracle_test +package integration_test_test import ( "context" diff --git a/x/oracle/keeper/test_utils.go b/x/oracle/keeper/test_utils.go index 904dc4c71..4d48451a2 100644 --- a/x/oracle/keeper/test_utils.go +++ b/x/oracle/keeper/test_utils.go @@ -3,6 +3,7 @@ package keeper import ( "github.com/NibiruChain/nibiru/x/common" + "github.com/cosmos/cosmos-sdk/std" "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/bank" distr "github.com/cosmos/cosmos-sdk/x/distribution" @@ -26,7 +27,6 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" simparams "github.com/cosmos/cosmos-sdk/simapp/params" - "github.com/cosmos/cosmos-sdk/std" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module"