diff --git a/local_node.sh b/local_node.sh index 1b066d7a7..3513323c0 100755 --- a/local_node.sh +++ b/local_node.sh @@ -165,6 +165,7 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then # x/dogfood # for easy testing, use an epoch of 1 minute and 5 epochs until unbonded. # i did not use 1 epoch to allow for testing that it does not happen at each epoch. + jq '.app_state["dogfood"]["params"]["asset_ids"][0]="0xdac17f958d2ee523a2206206994597c13d831ec7_0x65"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["dogfood"]["params"]["epoch_identifier"]="minute"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["dogfood"]["params"]["epochs_until_unbonded"]="5"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["dogfood"]["val_set"][0]["public_key"]="'"$CONSENSUS_KEY"'"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" @@ -178,9 +179,32 @@ if [[ $overwrite == "y" || $overwrite == "Y" ]]; then jq '.app_state["exomint"]["params"]["epoch_identifier"]="minute"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" # x/oracle - # set the asset_id to default asset - jq '.app_state["oracle"]["params"]["tokens"][1]["asset_id"]="0xdac17f958d2ee523a2206206994597c13d831ec7_0x65"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + # chain + jq '.app_state["oracle"]["params"]["chains"][1]["name"]="Ethereum"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["chains"][1]["desc"]="-"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + # token + jq '.app_state["oracle"]["params"]["tokens"][1]["name"]="ETH"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["tokens"][1]["chain_id"]="1"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["tokens"][1]["contract_address"]="0x"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" jq '.app_state["oracle"]["params"]["tokens"][1]["decimal"]="8"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["tokens"][1]["active"]=true' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["tokens"][1]["asset_id"]="0xdac17f958d2ee523a2206206994597c13d831ec7_0x65"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + # sources + jq '.app_state["oracle"]["params"]["sources"][1]["name"]="Chainlink"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["sources"][1]["entry"]["offchain"]["0"]=""' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["sources"][1]["entry"]["onchain"]={}' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["sources"][1]["valid"]=true' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["sources"][1]["deterministic"]=true' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + # rules + jq '.app_state["oracle"]["params"]["rules"][1]["source_ids"][0]="0"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["rules"][1]["nom"]=null' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + # token feeder + jq '.app_state["oracle"]["params"]["token_feeders"][1]["token_id"]="1"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["token_feeders"][1]["rule_id"]="1"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["token_feeders"][1]["start_round_id"]="1"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["token_feeders"][1]["start_base_block"]="20"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["token_feeders"][1]["interval"]="10"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" + jq '.app_state["oracle"]["params"]["token_feeders"][1]["end_block"]="0"' "$GENESIS" >"$TMP_GENESIS" && mv "$TMP_GENESIS" "$GENESIS" # custom epoch definitions can be added here, if required. # see https://github.com/ExocoreNetwork/exocore/blob/82b2509ad33ab7679592dcb1aa56a7a811128410/local_node.sh#L123 as an example diff --git a/testutil/keeper/oracle.go b/testutil/keeper/oracle.go index 1a7eb0ee2..40ee1d705 100644 --- a/testutil/keeper/oracle.go +++ b/testutil/keeper/oracle.go @@ -68,7 +68,34 @@ func OracleKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) { // Initialize params p4Test := types.DefaultParams() - p4Test.TokenFeeders[1].StartBaseBlock = 1 + p4Test.Chains = append(p4Test.Chains, &types.Chain{Name: "Ethereum", Desc: "-"}) + p4Test.Tokens = append(p4Test.Tokens, &types.Token{ + Name: "ETH", + ChainID: 1, + ContractAddress: "0x", + Decimal: 18, + Active: true, + AssetID: "0x0b34c4d876cd569129cf56bafabb3f9e97a4ff42_0x9ce1", + }) + p4Test.Sources = append(p4Test.Sources, &types.Source{ + Name: "Chainlink", + Entry: &types.Endpoint{ + Offchain: map[uint64]string{0: ""}, + }, + Valid: true, + Deterministic: true, + }) + p4Test.Rules = append(p4Test.Rules, &types.RuleSource{ + // all sources math + SourceIDs: []uint64{0}, + }) + p4Test.TokenFeeders = append(p4Test.TokenFeeders, &types.TokenFeeder{ + TokenID: 1, + RuleID: 1, + StartRoundID: 1, + StartBaseBlock: 1, + Interval: 10, + }) k.SetParams(ctx, p4Test) return &k, ctx diff --git a/testutil/network/genesis_data.go b/testutil/network/genesis_data.go index 6fc68971c..258a05007 100644 --- a/testutil/network/genesis_data.go +++ b/testutil/network/genesis_data.go @@ -57,10 +57,36 @@ var ( ) func init() { - // bond assetsIDs of ETH, NSTETH to ETH price - DefaultGenStateOracle.Params.Tokens[1].AssetID = fmt.Sprintf("%s,%s", ETHAssetID, NativeAssetID) - // set ETH tokenfeeder's 'StartBaseBlock' to 10 - DefaultGenStateOracle.Params.TokenFeeders[1].StartBaseBlock = 10 + DefaultGenStateOracle.Params.Chains = append(DefaultGenStateOracle.Params.Chains, &oracletypes.Chain{Name: "Ethereum", Desc: "-"}) + DefaultGenStateOracle.Params.Tokens = append(DefaultGenStateOracle.Params.Tokens, &oracletypes.Token{ + Name: "ETH", + ChainID: 1, + ContractAddress: "0x", + Decimal: 18, + Active: true, + // bond assetsIDs of ETH, NSTETH to ETH price + AssetID: fmt.Sprintf("%s,%s", ETHAssetID, NativeAssetID), + }) + DefaultGenStateOracle.Params.Sources = append(DefaultGenStateOracle.Params.Sources, &oracletypes.Source{ + Name: "Chainlink", + Entry: &oracletypes.Endpoint{ + Offchain: map[uint64]string{0: ""}, + }, + Valid: true, + Deterministic: true, + }) + DefaultGenStateOracle.Params.Rules = append(DefaultGenStateOracle.Params.Rules, &oracletypes.RuleSource{ + // all sources math + SourceIDs: []uint64{0}, + }) + DefaultGenStateOracle.Params.TokenFeeders = append(DefaultGenStateOracle.Params.TokenFeeders, &oracletypes.TokenFeeder{ + TokenID: 1, + RuleID: 1, + StartRoundID: 1, + // set ETH tokenfeeder's 'StartBaseBlock' to 10 + StartBaseBlock: 10, + Interval: 10, + }) // set NSTETH token and tokenFeeder DefaultGenStateOracle.Params.Tokens = append(DefaultGenStateOracle.Params.Tokens, &oracletypes.Token{ Name: "NSTETH", diff --git a/testutil/utils.go b/testutil/utils.go index 5671412fd..dfff56931 100644 --- a/testutil/utils.go +++ b/testutil/utils.go @@ -203,8 +203,34 @@ func (suite *BaseTestSuite) SetupWithGenesisValSet(genAccs []authtypes.GenesisAc // x/oracle initialization oracleDefaultParams := oracletypes.DefaultParams() - oracleDefaultParams.Tokens[1].AssetID = "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65" - oracleDefaultParams.TokenFeeders[1].StartBaseBlock = 1 + oracleDefaultParams.Chains = append(oracleDefaultParams.Chains, &oracletypes.Chain{Name: "Ethereum", Desc: "-"}) + oracleDefaultParams.Tokens = append(oracleDefaultParams.Tokens, &oracletypes.Token{ + Name: "ETH", + ChainID: 1, + ContractAddress: "0x", + Decimal: 18, + Active: true, + AssetID: "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65", + }) + oracleDefaultParams.Sources = append(oracleDefaultParams.Sources, &oracletypes.Source{ + Name: "Chainlink", + Entry: &oracletypes.Endpoint{ + Offchain: map[uint64]string{0: ""}, + }, + Valid: true, + Deterministic: true, + }) + oracleDefaultParams.Rules = append(oracleDefaultParams.Rules, &oracletypes.RuleSource{ + // all sources math + SourceIDs: []uint64{0}, + }) + oracleDefaultParams.TokenFeeders = append(oracleDefaultParams.TokenFeeders, &oracletypes.TokenFeeder{ + TokenID: 1, + RuleID: 1, + StartRoundID: 1, + StartBaseBlock: 1, + Interval: 10, + }) oracleDefaultParams.Tokens = append(oracleDefaultParams.Tokens, &oracletypes.Token{ Name: "USDT", ChainID: 1, @@ -380,6 +406,7 @@ func (suite *BaseTestSuite) SetupWithGenesisValSet(genAccs []authtypes.GenesisAc []dogfoodtypes.EpochToUndelegationRecordKeys{}, math.NewInt(power+power2), // must match total vote power ) + dogfoodGenesis.Params.AssetIDs = []string{assetID} dogfoodGenesis.Params.MinSelfDelegation = math.NewInt(100) genesisState[dogfoodtypes.ModuleName] = app.AppCodec().MustMarshalJSON(dogfoodGenesis) distributionGenesis := distributiontypes.NewGenesisState( diff --git a/x/dogfood/types/genesis_test.go b/x/dogfood/types/genesis_test.go index 36bd28a6a..ab985cb81 100644 --- a/x/dogfood/types/genesis_test.go +++ b/x/dogfood/types/genesis_test.go @@ -38,6 +38,7 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { ), ) params := types.DefaultParams() + params.AssetIDs = []string{"0x0b34c4d876cd569129cf56bafabb3f9e97a4ff42_0x9ce1"} testCases := []struct { name string genState *types.GenesisState @@ -54,8 +55,12 @@ func (suite *GenesisTestSuite) TestValidateGenesis() { expError: "nil last total power", }, { - name: "default", - genState: types.DefaultGenesis(), + name: "default", + genState: func() *types.GenesisState { + defaultGen := types.DefaultGenesis() + defaultGen.Params = params + return defaultGen + }(), expPass: false, // 0 voting power isn't permitted expError: "non-positive last total power", }, diff --git a/x/dogfood/types/params.go b/x/dogfood/types/params.go index c523e39ed..112308517 100644 --- a/x/dogfood/types/params.go +++ b/x/dogfood/types/params.go @@ -2,7 +2,6 @@ package types import ( "fmt" - "strings" sdkmath "cosmossdk.io/math" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" @@ -28,14 +27,15 @@ const ( // It is defined as a copy here so that we can use a value other than that in x/staking, if // necessary. DefaultHistoricalEntries = stakingtypes.DefaultHistoricalEntries - // DefaultAssetIDs is the default asset IDs accepted by the dogfood module. If multiple - // asset IDs are to be supported by default, separate them with a pipe character. - DefaultAssetIDs = "0xdac17f958d2ee523a2206206994597c13d831ec7_0x65" ) -// DefaultMinSelfDelegation is the default minimum self-delegation amount for a validator. -// It is denominated in USD. We do not support cents, since it is an integer. -var DefaultMinSelfDelegation = sdkmath.ZeroInt() // not a constant, hence var +var ( + // DefaultAssetIDs is the default asset IDs accepted by the dogfood module. + DefaultAssetIDs = []string{} + // DefaultMinSelfDelegation is the default minimum self-delegation amount for a validator. + // It is denominated in USD. We do not support cents, since it is an integer. + DefaultMinSelfDelegation = sdkmath.ZeroInt() +) // NewParams creates a new Params instance. func NewParams( @@ -63,7 +63,7 @@ func DefaultParams() Params { DefaultEpochIdentifier, DefaultMaxValidators, DefaultHistoricalEntries, - strings.Split(DefaultAssetIDs, "|"), + DefaultAssetIDs, DefaultMinSelfDelegation, ) } diff --git a/x/oracle/keeper/keeper_suite_test.go b/x/oracle/keeper/keeper_suite_test.go index 3bc01c6b0..9ce806875 100644 --- a/x/oracle/keeper/keeper_suite_test.go +++ b/x/oracle/keeper/keeper_suite_test.go @@ -73,7 +73,7 @@ func TestKeeper(t *testing.T) { } func (suite *KeeperSuite) Reset() { - p4Test := types.DefaultParams() + p4Test := DefaultParamsForTest() p4Test.TokenFeeders[1].StartBaseBlock = 1 suite.k.SetParams(suite.ctx, p4Test) suite.ctx = suite.ctx.WithBlockHeight(12) @@ -107,7 +107,7 @@ func (suite *KeeperSuite) SetupTest() { suite.ms = keeper.NewMsgServerImpl(suite.App.OracleKeeper) suite.ctx = suite.Ctx // Initialize params - p4Test := types.DefaultParams() + p4Test := DefaultParamsForTest() p4Test.TokenFeeders[1].StartBaseBlock = 1 suite.k.SetParams(suite.ctx, p4Test) suite.ctx = suite.ctx.WithBlockHeight(12) diff --git a/x/oracle/keeper/msg_server_create_price_test.go b/x/oracle/keeper/msg_server_create_price_test.go index 3b5b3121f..b2f64793c 100644 --- a/x/oracle/keeper/msg_server_create_price_test.go +++ b/x/oracle/keeper/msg_server_create_price_test.go @@ -68,7 +68,7 @@ var _ = Describe("MsgCreatePrice", func() { // c = ks.ms.Keeper.GetCaches() var pRes cache.ItemP c.GetCache(&pRes) - p4Test := types.DefaultParams() + p4Test := DefaultParamsForTest() p4Test.TokenFeeders[1].StartBaseBlock = 1 Expect(pRes).Should(BeEquivalentTo(p4Test)) }) diff --git a/x/oracle/keeper/msg_server_update_params_test.go b/x/oracle/keeper/msg_server_update_params_test.go index 9cf50d63b..c893c4a62 100644 --- a/x/oracle/keeper/msg_server_update_params_test.go +++ b/x/oracle/keeper/msg_server_update_params_test.go @@ -2,7 +2,9 @@ package keeper_test import ( reflect "reflect" + "time" + sdkmath "cosmossdk.io/math" dogfoodkeeper "github.com/ExocoreNetwork/exocore/x/dogfood/keeper" dogfoodtypes "github.com/ExocoreNetwork/exocore/x/dogfood/types" "github.com/ExocoreNetwork/exocore/x/oracle/types" @@ -13,6 +15,75 @@ import ( . "github.com/onsi/gomega" ) +func DefaultParamsForTest() types.Params { + return types.Params{ + Chains: []*types.Chain{ + {Name: "-", Desc: "-"}, + {Name: "Ethereum", Desc: "-"}, + }, + Tokens: []*types.Token{ + {}, + { + Name: "ETH", + ChainID: 1, + ContractAddress: "0x", + Decimal: 18, + Active: true, + AssetID: "0x0b34c4d876cd569129cf56bafabb3f9e97a4ff42_0x9ce1", + }, + }, + // source defines where to fetch the prices + Sources: []*types.Source{ + { + Name: "0 position is reserved", + }, + { + Name: "Chainlink", + Entry: &types.Endpoint{ + Offchain: map[uint64]string{0: ""}, + }, + Valid: true, + Deterministic: true, + }, + }, + // rules defines price from which sources are accepted, could be used to proof malicious + Rules: []*types.RuleSource{ + // 0 is reserved + {}, + { + // all sources math + SourceIDs: []uint64{0}, + }, + }, + // TokenFeeder describes when a token start to be updated with its price, and the frequency, endTime. + TokenFeeders: []*types.TokenFeeder{ + {}, + { + TokenID: 1, + RuleID: 1, + StartRoundID: 1, + StartBaseBlock: 1000000, + Interval: 10, + }, + }, + MaxNonce: 3, + ThresholdA: 2, + ThresholdB: 3, + // V1 set mode to 1 + Mode: types.ConsensusModeASAP, + MaxDetId: 5, + MaxSizePrices: 100, + Slashing: &types.SlashingParams{ + ReportedRoundsWindow: 100, + MinReportedPerWindow: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(2)), + OracleMissJailDuration: 600 * time.Second, + OracleMaliciousJailDuration: 30 * 24 * time.Hour, + SlashFractionMiss: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(20)), + SlashFractionMalicious: sdkmath.LegacyNewDec(1).Quo(sdkmath.LegacyNewDec(10)), + }, + } +} + var _ = Describe("MsgUpdateParams", Ordered, func() { var defaultParams types.Params var patcher *Patches @@ -24,7 +95,8 @@ var _ = Describe("MsgUpdateParams", Ordered, func() { BeforeEach(func() { ks.Reset() Expect(ks.ms).ToNot(BeNil()) - defaultParams = ks.k.GetParams(ks.ctx) + defaultParams = DefaultParamsForTest() + ks.k.SetParams(ks.ctx, defaultParams) privVal1 := mock.NewPV() pubKey1, _ := privVal1.GetPubKey() @@ -111,7 +183,7 @@ var _ = Describe("MsgUpdateParams", Ordered, func() { types.ErrInvalidParams.Wrap("invalid token to add, chain not found"), types.ErrInvalidParams.Wrap("invalid token to add, chain not found"), } - token := types.DefaultParams().Tokens[1] + token := DefaultParamsForTest().Tokens[1] token1 := *token token1.Decimal = 8 diff --git a/x/oracle/keeper/params_test.go b/x/oracle/keeper/params_test.go index 592a962bc..21980c3f2 100644 --- a/x/oracle/keeper/params_test.go +++ b/x/oracle/keeper/params_test.go @@ -176,7 +176,7 @@ func TestUpdateTokenFeederUpdate(t *testing.T) { err: nil, }, } - p := types.DefaultParams() + p := DefaultParamsForTest() p.Tokens = append(p.Tokens, &types.Token{ Name: "TEST", ChainID: 1, @@ -282,7 +282,7 @@ func TestTokenFeederValidate(t *testing.T) { } for _, testCase := range cases { t.Run(testCase.name, func(t *testing.T) { - p = types.DefaultParams() + p = DefaultParamsForTest() p.TokenFeeders[1].EndBlock = testCase.prevEndBlock p.TokenFeeders = append(p.TokenFeeders, testCase.feeder) err := p.Validate() diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 1e72de69e..a174fdd42 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -52,52 +52,24 @@ func DefaultParams() Params { return Params{ Chains: []*Chain{ {Name: "-", Desc: "-"}, - {Name: "Ethereum", Desc: "-"}, }, Tokens: []*Token{ {}, - { - Name: "ETH", - ChainID: 1, - ContractAddress: "0x", - Decimal: 18, - Active: true, - AssetID: "0x0b34c4d876cd569129cf56bafabb3f9e97a4ff42_0x9ce1", - }, }, // source defines where to fetch the prices Sources: []*Source{ { Name: "0 position is reserved", }, - { - Name: "Chainlink", - Entry: &Endpoint{ - Offchain: map[uint64]string{0: ""}, - }, - Valid: true, - Deterministic: true, - }, }, // rules defines price from which sources are accepted, could be used to proof malicious Rules: []*RuleSource{ // 0 is reserved {}, - { - // all sources math - SourceIDs: []uint64{0}, - }, }, // TokenFeeder describes when a token start to be updated with its price, and the frequency, endTime. TokenFeeders: []*TokenFeeder{ {}, - { - TokenID: 1, - RuleID: 1, - StartRoundID: 1, - StartBaseBlock: 1000000, - Interval: 10, - }, }, MaxNonce: 3, ThresholdA: 2,