diff --git a/.codecov.yml b/.codecov.yml
index 7bbc9f1b..0d6b82c3 100644
--- a/.codecov.yml
+++ b/.codecov.yml
@@ -20,5 +20,15 @@ ignore:
- "contrib/"
- "docs/"
- "networks/"
+ - "proto/"
+ - "scripts/"
+ - "thrid_party/"
+ - "docker/"
+ - "client/"
+ - "custom/"
- "**/cli"
- "**/rest"
+ - "**/*.pb.go"
+ - "**/*.pb.gw.go"
+ - "**/test_utils.go"
+ - "**/module.go"
diff --git a/README.md b/README.md
index d49bc0ce..98f7d840 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
Full-node software implementing the Terra protocol
-
+
diff --git a/go.mod b/go.mod
index 5272182b..1bc12c31 100644
--- a/go.mod
+++ b/go.mod
@@ -8,6 +8,7 @@ require (
github.com/cosmos/ibc-go v1.1.5
github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.2
+ github.com/google/gofuzz v1.2.0
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/pkg/errors v0.9.1
diff --git a/go.sum b/go.sum
index a80ac3af..4bf0dc1e 100644
--- a/go.sum
+++ b/go.sum
@@ -358,8 +358,9 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
diff --git a/x/oracle/abci.go b/x/oracle/abci.go
index 07f2fc1b..37ae9a52 100644
--- a/x/oracle/abci.go
+++ b/x/oracle/abci.go
@@ -57,7 +57,7 @@ func EndBlocker(ctx sdk.Context, k keeper.Keeper) {
// NOTE: **Make abstain votes to have zero vote power**
voteMap := k.OrganizeBallotByDenom(ctx, validatorClaimMap)
- if referenceTerra := pickReferenceTerra(ctx, k, voteTargets, voteMap); referenceTerra != "" {
+ if referenceTerra := PickReferenceTerra(ctx, k, voteTargets, voteMap); referenceTerra != "" {
// make voteMap of Reference Terra to calculate cross exchange rates
ballotRT := voteMap[referenceTerra]
voteMapRT := ballotRT.ToMap()
diff --git a/x/oracle/genesis_test.go b/x/oracle/genesis_test.go
index 4b08d4b5..1c2b2720 100644
--- a/x/oracle/genesis_test.go
+++ b/x/oracle/genesis_test.go
@@ -21,6 +21,7 @@ func TestExportInitGenesis(t *testing.T) {
input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, keeper.ValAddrs[0], types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "foo", ExchangeRate: sdk.NewDec(123)}}, keeper.ValAddrs[0]))
input.OracleKeeper.SetTobinTax(input.Ctx, "denom", sdk.NewDecWithPrec(123, 3))
input.OracleKeeper.SetTobinTax(input.Ctx, "denom2", sdk.NewDecWithPrec(123, 3))
+ input.OracleKeeper.SetMissCounter(input.Ctx, keeper.ValAddrs[0], 10)
genesis := oracle.ExportGenesis(input.Ctx, input.OracleKeeper)
newInput := keeper.CreateTestInput(t)
@@ -29,3 +30,104 @@ func TestExportInitGenesis(t *testing.T) {
require.Equal(t, genesis, newGenesis)
}
+
+func TestInitGenesis(t *testing.T) {
+ input, _ := setup(t)
+ genesis := types.DefaultGenesisState()
+ require.NotPanics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+
+ genesis.FeederDelegations = []types.FeederDelegation{{
+ FeederAddress: keeper.Addrs[0].String(),
+ ValidatorAddress: "invalid",
+ }}
+
+ require.Panics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+
+ genesis.FeederDelegations = []types.FeederDelegation{{
+ FeederAddress: "invalid",
+ ValidatorAddress: keeper.ValAddrs[0].String(),
+ }}
+
+ require.Panics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+
+ genesis.FeederDelegations = []types.FeederDelegation{{
+ FeederAddress: keeper.Addrs[0].String(),
+ ValidatorAddress: keeper.ValAddrs[0].String(),
+ }}
+
+ genesis.MissCounters = []types.MissCounter{
+ {
+ ValidatorAddress: "invalid",
+ MissCounter: 10,
+ },
+ }
+
+ require.Panics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+
+ genesis.MissCounters = []types.MissCounter{
+ {
+ ValidatorAddress: keeper.ValAddrs[0].String(),
+ MissCounter: 10,
+ },
+ }
+
+ genesis.AggregateExchangeRatePrevotes = []types.AggregateExchangeRatePrevote{
+ {
+ Hash: "hash",
+ Voter: "invalid",
+ SubmitBlock: 100,
+ },
+ }
+
+ require.Panics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+
+ genesis.AggregateExchangeRatePrevotes = []types.AggregateExchangeRatePrevote{
+ {
+ Hash: "hash",
+ Voter: keeper.ValAddrs[0].String(),
+ SubmitBlock: 100,
+ },
+ }
+
+ genesis.AggregateExchangeRateVotes = []types.AggregateExchangeRateVote{
+ {
+ ExchangeRateTuples: []types.ExchangeRateTuple{
+ {
+ Denom: "ukrw",
+ ExchangeRate: sdk.NewDec(10),
+ },
+ },
+ Voter: "invalid",
+ },
+ }
+
+ require.Panics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+
+ genesis.AggregateExchangeRateVotes = []types.AggregateExchangeRateVote{
+ {
+ ExchangeRateTuples: []types.ExchangeRateTuple{
+ {
+ Denom: "ukrw",
+ ExchangeRate: sdk.NewDec(10),
+ },
+ },
+ Voter: keeper.ValAddrs[0].String(),
+ },
+ }
+
+ require.NotPanics(t, func() {
+ oracle.InitGenesis(input.Ctx, input.OracleKeeper, genesis)
+ })
+}
diff --git a/x/oracle/keeper/legacy_querier_test.go b/x/oracle/keeper/legacy_querier_test.go
index 7ee1ea84..b0e1902a 100644
--- a/x/oracle/keeper/legacy_querier_test.go
+++ b/x/oracle/keeper/legacy_querier_test.go
@@ -28,6 +28,20 @@ func TestLegacyNewLegacyQuerier(t *testing.T) {
require.NoError(t, err)
}
+func TestLegacyFilter(t *testing.T) {
+ input := CreateTestInput(t)
+
+ querier := NewLegacyQuerier(input.OracleKeeper, input.Cdc)
+
+ query := abci.RequestQuery{
+ Path: "",
+ Data: []byte{},
+ }
+
+ _, err := querier(input.Ctx, []string{"invalid"}, query)
+ require.Error(t, err)
+}
+
func TestLegacyQueryParams(t *testing.T) {
input := CreateTestInput(t)
querier := NewLegacyQuerier(input.OracleKeeper, input.Cdc)
@@ -46,6 +60,31 @@ func TestLegacyQueryParams(t *testing.T) {
require.Equal(t, input.OracleKeeper.GetParams(input.Ctx), params)
}
+func TestLegacyQueryMissCounter(t *testing.T) {
+ input := CreateTestInput(t)
+ querier := NewLegacyQuerier(input.OracleKeeper, input.Cdc)
+
+ queryParams := types.NewQueryMissCounterParams(ValAddrs[0])
+ bz, err := input.Cdc.MarshalJSON(queryParams)
+ require.NoError(t, err)
+
+ _, err = querier(input.Ctx, []string{types.QueryMissCounter}, abci.RequestQuery{})
+ require.Error(t, err)
+
+ req := abci.RequestQuery{
+ Path: "",
+ Data: bz,
+ }
+
+ res, err := querier(input.Ctx, []string{types.QueryMissCounter}, req)
+ require.NoError(t, err)
+
+ var missCounter uint64
+ err = input.Cdc.UnmarshalJSON(res, &missCounter)
+ require.NoError(t, err)
+ require.Equal(t, input.OracleKeeper.GetMissCounter(input.Ctx, ValAddrs[0]), missCounter)
+}
+
func TestLegacyQueryExchangeRate(t *testing.T) {
input := CreateTestInput(t)
querier := NewLegacyQuerier(input.OracleKeeper, input.Cdc)
@@ -58,6 +97,9 @@ func TestLegacyQueryExchangeRate(t *testing.T) {
bz, err := input.Cdc.MarshalJSON(queryParams)
require.NoError(t, err)
+ _, err = querier(input.Ctx, []string{types.QueryExchangeRate}, abci.RequestQuery{})
+ require.Error(t, err)
+
req := abci.RequestQuery{
Path: "",
Data: bz,
@@ -126,6 +168,9 @@ func TestLegacyQueryFeederDelegation(t *testing.T) {
bz, err := input.Cdc.MarshalJSON(queryParams)
require.NoError(t, err)
+ _, err = querier(input.Ctx, []string{types.QueryFeederDelegation}, abci.RequestQuery{})
+ require.Error(t, err)
+
req := abci.RequestQuery{
Path: "",
Data: bz,
@@ -155,6 +200,9 @@ func TestLegacyQueryAggregatePrevote(t *testing.T) {
bz, err := input.Cdc.MarshalJSON(queryParams)
require.NoError(t, err)
+ _, err = querier(input.Ctx, []string{types.QueryAggregatePrevote}, abci.RequestQuery{})
+ require.Error(t, err)
+
req := abci.RequestQuery{
Path: "",
Data: bz,
@@ -204,12 +252,7 @@ func TestLegacyQueryAggregatePrevotes(t *testing.T) {
return bytes.Compare(addr1, addr2) == -1
})
- req := abci.RequestQuery{
- Path: "",
- Data: nil,
- }
-
- res, err := querier(input.Ctx, []string{types.QueryAggregatePrevotes}, req)
+ res, err := querier(input.Ctx, []string{types.QueryAggregatePrevotes}, abci.RequestQuery{})
require.NoError(t, err)
var prevotes []types.AggregateExchangeRatePrevote
@@ -234,6 +277,9 @@ func TestLegacyQueryAggregateVote(t *testing.T) {
bz, err := input.Cdc.MarshalJSON(queryParams)
require.NoError(t, err)
+ _, err = querier(input.Ctx, []string{types.QueryAggregateVote}, abci.RequestQuery{})
+ require.Error(t, err)
+
req := abci.RequestQuery{
Path: "",
Data: bz,
@@ -283,12 +329,7 @@ func TestLegacyQueryAggregateVotes(t *testing.T) {
return bytes.Compare(addr1, addr2) == -1
})
- req := abci.RequestQuery{
- Path: "",
- Data: nil,
- }
-
- res, err := querier(input.Ctx, []string{types.QueryAggregateVotes}, req)
+ res, err := querier(input.Ctx, []string{types.QueryAggregateVotes}, abci.RequestQuery{})
require.NoError(t, err)
var votes []types.AggregateExchangeRateVote
@@ -309,12 +350,7 @@ func TestLegacyQueryVoteTargets(t *testing.T) {
input.OracleKeeper.SetTobinTax(input.Ctx, target, sdk.OneDec())
}
- req := abci.RequestQuery{
- Path: "",
- Data: nil,
- }
-
- res, err := querier(input.Ctx, []string{types.QueryVoteTargets}, req)
+ res, err := querier(input.Ctx, []string{types.QueryVoteTargets}, abci.RequestQuery{})
require.NoError(t, err)
var voteTargetsRes []string
@@ -341,12 +377,7 @@ func TestLegacyQueryTobinTaxes(t *testing.T) {
input.OracleKeeper.SetTobinTax(input.Ctx, item.Name, item.TobinTax)
}
- req := abci.RequestQuery{
- Path: "",
- Data: nil,
- }
-
- res, err := querier(input.Ctx, []string{types.QueryTobinTaxes}, req)
+ res, err := querier(input.Ctx, []string{types.QueryTobinTaxes}, abci.RequestQuery{})
require.NoError(t, err)
var tobinTaxesRes types.DenomList
@@ -366,6 +397,9 @@ func TestLegacyQueryTobinTax(t *testing.T) {
bz, err := input.Cdc.MarshalJSON(queryParams)
require.NoError(t, err)
+ _, err = querier(input.Ctx, []string{types.QueryTobinTax}, abci.RequestQuery{})
+ require.Error(t, err)
+
req := abci.RequestQuery{
Path: "",
Data: bz,
diff --git a/x/oracle/keeper/msg_server_test.go b/x/oracle/keeper/msg_server_test.go
new file mode 100644
index 00000000..28ed4534
--- /dev/null
+++ b/x/oracle/keeper/msg_server_test.go
@@ -0,0 +1,170 @@
+package keeper
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ core "github.com/terra-money/core/types"
+ "github.com/terra-money/core/x/oracle/types"
+
+ "github.com/cosmos/cosmos-sdk/x/staking"
+)
+
+func TestMsgServer_FeederDelegation(t *testing.T) {
+ input, msgServer := setup(t)
+
+ salt := "1"
+ hash := types.GetAggregateVoteHash(salt, randomExchangeRate.String()+core.MicroSDRDenom, ValAddrs[0])
+
+ // Case 1: empty message
+ delegateFeedConsentMsg := types.MsgDelegateFeedConsent{}
+ _, err := msgServer.DelegateFeedConsent(sdk.WrapSDKContext(input.Ctx), &delegateFeedConsentMsg)
+ require.Error(t, err)
+
+ // Case 2: Normal Prevote - without delegation
+ prevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg)
+ require.NoError(t, err)
+
+ // Case 2.1: Normal Prevote - with delegation fails
+ prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[1], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg)
+ require.Error(t, err)
+
+ // Case 2.2: Normal Vote - without delegation
+ voteMsg := types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+core.MicroSDRDenom, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg)
+ require.NoError(t, err)
+
+ // Case 2.3: Normal Vote - with delegation fails
+ voteMsg = types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+core.MicroSDRDenom, Addrs[1], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg)
+ require.Error(t, err)
+
+ // Case 3: Normal MsgDelegateFeedConsent succeeds
+ msg := types.NewMsgDelegateFeedConsent(ValAddrs[0], Addrs[1])
+ _, err = msgServer.DelegateFeedConsent(sdk.WrapSDKContext(input.Ctx), msg)
+ require.NoError(t, err)
+
+ // Case 4.1: Normal Prevote - without delegation fails
+ prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[2], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg)
+ require.Error(t, err)
+
+ // Case 4.2: Normal Prevote - with delegation succeeds
+ prevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[1], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), prevoteMsg)
+ require.NoError(t, err)
+
+ // Case 4.3: Normal Vote - without delegation fails
+ voteMsg = types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+core.MicroSDRDenom, Addrs[2], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg)
+ require.Error(t, err)
+
+ // Case 4.4: Normal Vote - with delegation succeeds
+ voteMsg = types.NewMsgAggregateExchangeRateVote(salt, randomExchangeRate.String()+core.MicroSDRDenom, Addrs[1], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx.WithBlockHeight(1)), voteMsg)
+ require.NoError(t, err)
+}
+
+func TestMsgServer_AggregatePrevoteVote(t *testing.T) {
+ input, msgServer := setup(t)
+
+ salt := "1"
+ exchangeRatesStr := fmt.Sprintf("1000.23%s,0.29%s,0.27%s", core.MicroKRWDenom, core.MicroUSDDenom, core.MicroSDRDenom)
+ otherExchangeRateStr := fmt.Sprintf("1000.12%s,0.29%s,0.27%s", core.MicroKRWDenom, core.MicroUSDDenom, core.MicroUSDDenom)
+ unintendedExchageRateStr := fmt.Sprintf("1000.23%s,0.29%s,0.27%s", core.MicroKRWDenom, core.MicroUSDDenom, core.MicroCNYDenom)
+ invalidExchangeRateStr := fmt.Sprintf("1000.23%s,0.29%s,0.27", core.MicroKRWDenom, core.MicroUSDDenom)
+
+ hash := types.GetAggregateVoteHash(salt, exchangeRatesStr, ValAddrs[0])
+
+ aggregateExchangeRatePrevoteMsg := types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[0], ValAddrs[0])
+ _, err := msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg)
+ require.NoError(t, err)
+
+ // Unauthorized feeder
+ aggregateExchangeRatePrevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[1], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg)
+ require.Error(t, err)
+
+ // Invalid addr
+ aggregateExchangeRatePrevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, sdk.AccAddress{}, ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg)
+ require.Error(t, err)
+
+ // Invalid validator addr
+ aggregateExchangeRatePrevoteMsg = types.NewMsgAggregateExchangeRatePrevote(hash, Addrs[0], sdk.ValAddress{})
+ _, err = msgServer.AggregateExchangeRatePrevote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRatePrevoteMsg)
+ require.Error(t, err)
+
+ // Invalid reveal period
+ aggregateExchangeRateVoteMsg := types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.Error(t, err)
+
+ // Invalid reveal period
+ input.Ctx = input.Ctx.WithBlockHeight(2)
+ aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.Error(t, err)
+
+ // Other exchange rate with valid real period
+ input.Ctx = input.Ctx.WithBlockHeight(1)
+ aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, otherExchangeRateStr, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.Error(t, err)
+
+ // Invalid exchange rate with valid real period
+ input.Ctx = input.Ctx.WithBlockHeight(1)
+ aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, invalidExchangeRateStr, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.Error(t, err)
+
+ // Unauthorized feeder
+ aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, invalidExchangeRateStr, Addrs[1], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.Error(t, err)
+
+ // Unintended denom vote
+ aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, unintendedExchageRateStr, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.Error(t, err)
+
+ // Valid exchange rate reveal submission
+ input.Ctx = input.Ctx.WithBlockHeight(1)
+ aggregateExchangeRateVoteMsg = types.NewMsgAggregateExchangeRateVote(salt, exchangeRatesStr, Addrs[0], ValAddrs[0])
+ _, err = msgServer.AggregateExchangeRateVote(sdk.WrapSDKContext(input.Ctx), aggregateExchangeRateVoteMsg)
+ require.NoError(t, err)
+}
+
+var (
+ stakingAmt = sdk.TokensFromConsensusPower(10, sdk.DefaultPowerReduction)
+ randomExchangeRate = sdk.NewDec(1700)
+)
+
+func setup(t *testing.T) (TestInput, types.MsgServer) {
+ input := CreateTestInput(t)
+ params := input.OracleKeeper.GetParams(input.Ctx)
+ params.VotePeriod = 1
+ params.SlashWindow = 100
+ params.RewardDistributionWindow = 100
+ input.OracleKeeper.SetParams(input.Ctx, params)
+ msgServer := NewMsgServerImpl(input.OracleKeeper)
+
+ sh := staking.NewHandler(input.StakingKeeper)
+
+ // Validator created
+ _, err := sh(input.Ctx, NewTestMsgCreateValidator(ValAddrs[0], ValPubKeys[0], stakingAmt))
+ require.NoError(t, err)
+ _, err = sh(input.Ctx, NewTestMsgCreateValidator(ValAddrs[1], ValPubKeys[1], stakingAmt))
+ require.NoError(t, err)
+ _, err = sh(input.Ctx, NewTestMsgCreateValidator(ValAddrs[2], ValPubKeys[2], stakingAmt))
+ require.NoError(t, err)
+ staking.EndBlocker(input.Ctx, input.StakingKeeper)
+
+ return input, msgServer
+}
diff --git a/x/oracle/keeper/querier_test.go b/x/oracle/keeper/querier_test.go
index 19d47068..41550e60 100644
--- a/x/oracle/keeper/querier_test.go
+++ b/x/oracle/keeper/querier_test.go
@@ -32,6 +32,10 @@ func TestQueryExchangeRate(t *testing.T) {
rate := sdk.NewDec(1700)
input.OracleKeeper.SetLunaExchangeRate(input.Ctx, core.MicroSDRDenom, rate)
+ // empty request
+ _, err := querier.ExchangeRate(ctx, nil)
+ require.Error(t, err)
+
// Query to grpc
res, err := querier.ExchangeRate(ctx, &types.QueryExchangeRateRequest{
Denom: core.MicroSDRDenom,
@@ -40,6 +44,26 @@ func TestQueryExchangeRate(t *testing.T) {
require.Equal(t, rate, res.ExchangeRate)
}
+func TestQueryMissCounter(t *testing.T) {
+ input := CreateTestInput(t)
+ ctx := sdk.WrapSDKContext(input.Ctx)
+ querier := NewQuerier(input.OracleKeeper)
+
+ missCounter := uint64(1)
+ input.OracleKeeper.SetMissCounter(input.Ctx, ValAddrs[0], missCounter)
+
+ // empty request
+ _, err := querier.MissCounter(ctx, nil)
+ require.Error(t, err)
+
+ // Query to grpc
+ res, err := querier.MissCounter(ctx, &types.QueryMissCounterRequest{
+ ValidatorAddr: ValAddrs[0].String(),
+ })
+ require.NoError(t, err)
+ require.Equal(t, missCounter, res.MissCounter)
+}
+
func TestQueryExchangeRates(t *testing.T) {
input := CreateTestInput(t)
ctx := sdk.WrapSDKContext(input.Ctx)
@@ -87,6 +111,10 @@ func TestQueryFeederDelegation(t *testing.T) {
input.OracleKeeper.SetFeederDelegation(input.Ctx, ValAddrs[0], Addrs[1])
+ // empty request
+ _, err := querier.FeederDelegation(ctx, nil)
+ require.Error(t, err)
+
res, err := querier.FeederDelegation(ctx, &types.QueryFeederDelegationRequest{
ValidatorAddr: ValAddrs[0].String(),
})
@@ -112,6 +140,10 @@ func TestQueryAggregatePrevote(t *testing.T) {
require.NoError(t, err)
require.Equal(t, prevote1, res.AggregatePrevote)
+ // empty request
+ _, err = querier.AggregatePrevote(ctx, nil)
+ require.Error(t, err)
+
// validator 1 address params
res, err = querier.AggregatePrevote(ctx, &types.QueryAggregatePrevoteRequest{
ValidatorAddr: ValAddrs[1].String(),
@@ -154,6 +186,10 @@ func TestQueryAggregateVote(t *testing.T) {
vote2 := types.NewAggregateExchangeRateVote(types.ExchangeRateTuples{{Denom: "", ExchangeRate: sdk.OneDec()}}, ValAddrs[1])
input.OracleKeeper.SetAggregateExchangeRateVote(input.Ctx, ValAddrs[1], vote2)
+ // empty request
+ _, err := querier.AggregateVote(ctx, nil)
+ require.Error(t, err)
+
// validator 0 address params
res, err := querier.AggregateVote(ctx, &types.QueryAggregateVoteRequest{
ValidatorAddr: ValAddrs[0].String(),
@@ -243,6 +279,10 @@ func TestQueryTobinTax(t *testing.T) {
denom := types.Denom{Name: core.MicroKRWDenom, TobinTax: sdk.OneDec()}
input.OracleKeeper.SetTobinTax(input.Ctx, denom.Name, denom.TobinTax)
+ // empty request
+ _, err := querier.TobinTax(ctx, nil)
+ require.Error(t, err)
+
res, err := querier.TobinTax(ctx, &types.QueryTobinTaxRequest{
Denom: core.MicroKRWDenom,
})
diff --git a/x/oracle/tally.go b/x/oracle/tally.go
index c33b5c4d..d30dd94d 100644
--- a/x/oracle/tally.go
+++ b/x/oracle/tally.go
@@ -50,10 +50,10 @@ func ballotIsPassing(ballot types.ExchangeRateBallot, thresholdVotes sdk.Int) (s
return ballotPower, !ballotPower.IsZero() && ballotPower.GTE(thresholdVotes)
}
-// choose Reference Terra with the highest voter turnout
+// PickReferenceTerra choose Reference Terra with the highest voter turnout
// If the voting power of the two denominations is the same,
// select reference Terra in alphabetical order.
-func pickReferenceTerra(ctx sdk.Context, k keeper.Keeper, voteTargets map[string]sdk.Dec, voteMap map[string]types.ExchangeRateBallot) string {
+func PickReferenceTerra(ctx sdk.Context, k keeper.Keeper, voteTargets map[string]sdk.Dec, voteMap map[string]types.ExchangeRateBallot) string {
largestBallotPower := int64(0)
referenceTerra := ""
diff --git a/x/oracle/tally_fuzz_test.go b/x/oracle/tally_fuzz_test.go
new file mode 100644
index 00000000..7aaab86d
--- /dev/null
+++ b/x/oracle/tally_fuzz_test.go
@@ -0,0 +1,139 @@
+package oracle_test
+
+import (
+ "sort"
+ "testing"
+
+ fuzz "github.com/google/gofuzz"
+ "github.com/stretchr/testify/require"
+
+ "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
+ sdk "github.com/cosmos/cosmos-sdk/types"
+
+ "github.com/terra-money/core/x/oracle"
+ "github.com/terra-money/core/x/oracle/types"
+)
+
+func TestFuzz_Tally(t *testing.T) {
+ validators := map[string]int64{}
+
+ f := fuzz.New().NilChance(0).Funcs(
+ func(e *sdk.Dec, c fuzz.Continue) {
+ *e = sdk.NewDec(c.Int63())
+ },
+ func(e *map[string]int64, c fuzz.Continue) {
+ numValidators := c.Intn(100) + 5
+
+ for i := 0; i < numValidators; i++ {
+ (*e)[sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()).String()] = c.Int63n(100)
+ }
+ },
+ func(e *map[string]types.Claim, c fuzz.Continue) {
+ for validator, power := range validators {
+ addr, err := sdk.ValAddressFromBech32(validator)
+ require.NoError(t, err)
+ (*e)[validator] = types.NewClaim(power, 0, 0, addr)
+ }
+ },
+ func(e *types.ExchangeRateBallot, c fuzz.Continue) {
+
+ ballot := types.ExchangeRateBallot{}
+ for addr, power := range validators {
+ addr, _ := sdk.ValAddressFromBech32(addr)
+
+ var rate sdk.Dec
+ c.Fuzz(&rate)
+
+ ballot = append(ballot, types.NewVoteForTally(rate, c.RandString(), addr, power))
+ }
+
+ sort.Sort(ballot)
+
+ *e = ballot
+ },
+ )
+
+ // set random denoms and validators
+ f.Fuzz(&validators)
+
+ input, _ := setup(t)
+
+ claimMap := map[string]types.Claim{}
+ f.Fuzz(&claimMap)
+
+ ballot := types.ExchangeRateBallot{}
+ f.Fuzz(&ballot)
+
+ var rewardBand sdk.Dec
+ f.Fuzz(&rewardBand)
+
+ require.NotPanics(t, func() {
+ oracle.Tally(input.Ctx, ballot, rewardBand, claimMap)
+ })
+}
+
+func TestFuzz_PickReferenceTerra(t *testing.T) {
+ var denoms []string
+
+ f := fuzz.New().NilChance(0).Funcs(
+ func(e *[]string, c fuzz.Continue) {
+ numDenoms := c.Intn(100) + 5
+
+ for i := 0; i < numDenoms; i++ {
+ *e = append(*e, c.RandString())
+ }
+ },
+ func(e *sdk.Dec, c fuzz.Continue) {
+ *e = sdk.NewDec(c.Int63())
+ },
+ func(e *map[string]sdk.Dec, c fuzz.Continue) {
+ for _, denom := range denoms {
+ var rate sdk.Dec
+ c.Fuzz(&rate)
+
+ (*e)[denom] = rate
+ }
+ },
+ func(e *map[string]int64, c fuzz.Continue) {
+ numValidator := c.Intn(100) + 5
+ for i := 0; i < numValidator; i++ {
+ (*e)[sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()).String()] = int64(c.Intn(100) + 1)
+ }
+ },
+ func(e *map[string]types.ExchangeRateBallot, c fuzz.Continue) {
+ validators := map[string]int64{}
+ c.Fuzz(&validators)
+
+ for _, denom := range denoms {
+ ballot := types.ExchangeRateBallot{}
+
+ for addr, power := range validators {
+ addr, _ := sdk.ValAddressFromBech32(addr)
+
+ var rate sdk.Dec
+ c.Fuzz(&rate)
+
+ ballot = append(ballot, types.NewVoteForTally(rate, denom, addr, power))
+ }
+
+ sort.Sort(ballot)
+ (*e)[denom] = ballot
+ }
+ },
+ )
+
+ // set random denoms
+ f.Fuzz(&denoms)
+
+ input, _ := setup(t)
+
+ voteTargets := map[string]sdk.Dec{}
+ f.Fuzz(&voteTargets)
+
+ voteMap := map[string]types.ExchangeRateBallot{}
+ f.Fuzz(&voteMap)
+
+ require.NotPanics(t, func() {
+ oracle.PickReferenceTerra(input.Ctx, input.OracleKeeper, voteTargets, voteMap)
+ })
+}
diff --git a/x/oracle/types/ballot_test.go b/x/oracle/types/ballot_test.go
index 59485044..2179bd2a 100644
--- a/x/oracle/types/ballot_test.go
+++ b/x/oracle/types/ballot_test.go
@@ -1,4 +1,4 @@
-package types
+package types_test
import (
"fmt"
@@ -16,15 +16,16 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
core "github.com/terra-money/core/types"
+ "github.com/terra-money/core/x/oracle/types"
)
func TestToMap(t *testing.T) {
tests := struct {
- votes []VoteForTally
+ votes []types.VoteForTally
isValid []bool
}{
- []VoteForTally{
+ []types.VoteForTally{
{
Voter: sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()),
@@ -50,7 +51,7 @@ func TestToMap(t *testing.T) {
[]bool{true, false, true},
}
- pb := ExchangeRateBallot(tests.votes)
+ pb := types.ExchangeRateBallot(tests.votes)
mapData := pb.ToMap()
for i, vote := range tests.votes {
exchangeRate, ok := mapData[string(vote.Voter)]
@@ -86,27 +87,29 @@ func TestToCrossRate(t *testing.T) {
},
}
- pbBase := ExchangeRateBallot{}
- pbQuote := ExchangeRateBallot{}
- cb := ExchangeRateBallot{}
+ pbBase := types.ExchangeRateBallot{}
+ pbQuote := types.ExchangeRateBallot{}
+ cb := types.ExchangeRateBallot{}
for _, data := range data {
valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address())
if !data.base.IsZero() {
- pbBase = append(pbBase, NewVoteForTally(data.base, core.MicroKRWDenom, valAddr, 100))
+ pbBase = append(pbBase, types.NewVoteForTally(data.base, core.MicroKRWDenom, valAddr, 100))
}
- pbQuote = append(pbQuote, NewVoteForTally(data.quote, core.MicroKRWDenom, valAddr, 100))
+ pbQuote = append(pbQuote, types.NewVoteForTally(data.quote, core.MicroKRWDenom, valAddr, 100))
if !data.base.IsZero() && !data.quote.IsZero() {
- cb = append(cb, NewVoteForTally(data.base.Quo(data.quote), core.MicroKRWDenom, valAddr, 100))
+ cb = append(cb, types.NewVoteForTally(data.base.Quo(data.quote), core.MicroKRWDenom, valAddr, 100))
} else {
- cb = append(cb, NewVoteForTally(sdk.ZeroDec(), core.MicroKRWDenom, valAddr, 0))
+ cb = append(cb, types.NewVoteForTally(sdk.ZeroDec(), core.MicroKRWDenom, valAddr, 0))
}
}
+ baseMapBallot := pbBase.ToMap()
+ require.Equal(t, cb, pbQuote.ToCrossRate(baseMapBallot))
+
sort.Sort(cb)
- baseMapBallot := pbBase.ToMap()
require.Equal(t, cb, pbQuote.ToCrossRateWithSort(baseMapBallot))
}
@@ -125,13 +128,13 @@ func TestSqrt(t *testing.T) {
func TestPBPower(t *testing.T) {
ctx := sdk.NewContext(nil, tmproto.Header{}, false, nil)
- _, valAccAddrs, sk := GenerateRandomTestCase()
- pb := ExchangeRateBallot{}
+ _, valAccAddrs, sk := types.GenerateRandomTestCase()
+ pb := types.ExchangeRateBallot{}
ballotPower := int64(0)
for i := 0; i < len(sk.Validators()); i++ {
power := sk.Validator(ctx, valAccAddrs[i]).GetConsensusPower(sdk.DefaultPowerReduction)
- vote := NewVoteForTally(
+ vote := types.NewVoteForTally(
sdk.ZeroDec(),
core.MicroSDRDenom,
valAccAddrs[i],
@@ -150,7 +153,7 @@ func TestPBPower(t *testing.T) {
// Mix in a fake validator, the total power should not have changed.
pubKey := secp256k1.GenPrivKey().PubKey()
faceValAddr := sdk.ValAddress(pubKey.Address())
- fakeVote := NewVoteForTally(
+ fakeVote := types.NewVoteForTally(
sdk.OneDec(),
core.MicroSDRDenom,
faceValAddr,
@@ -167,6 +170,7 @@ func TestPBWeightedMedian(t *testing.T) {
weights []int64
isValidator []bool
median sdk.Dec
+ panic bool
}{
{
// Supermajority one number
@@ -174,6 +178,7 @@ func TestPBWeightedMedian(t *testing.T) {
[]int64{1, 1, 100, 1},
[]bool{true, true, true, true},
sdk.NewDec(10),
+ false,
},
{
// Adding fake validator doesn't change outcome
@@ -181,6 +186,7 @@ func TestPBWeightedMedian(t *testing.T) {
[]int64{1, 1, 100, 1, 10000},
[]bool{true, true, true, true, false},
sdk.NewDec(10),
+ false,
},
{
// Tie votes
@@ -188,6 +194,7 @@ func TestPBWeightedMedian(t *testing.T) {
[]int64{1, 100, 100, 1},
[]bool{true, true, true, true},
sdk.NewDec(2),
+ false,
},
{
// No votes
@@ -195,11 +202,20 @@ func TestPBWeightedMedian(t *testing.T) {
[]int64{},
[]bool{true, true, true, true},
sdk.NewDec(0),
+ false,
+ },
+ {
+ // not sorted panic
+ []int64{2, 1, 10, 100000},
+ []int64{1, 1, 100, 1},
+ []bool{true, true, true, true},
+ sdk.NewDec(10),
+ true,
},
}
for _, tc := range tests {
- pb := ExchangeRateBallot{}
+ pb := types.ExchangeRateBallot{}
for i, input := range tc.inputs {
valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address())
@@ -208,7 +224,7 @@ func TestPBWeightedMedian(t *testing.T) {
power = 0
}
- vote := NewVoteForTally(
+ vote := types.NewVoteForTally(
sdk.NewDec(int64(input)),
core.MicroSDRDenom,
valAddr,
@@ -218,7 +234,12 @@ func TestPBWeightedMedian(t *testing.T) {
pb = append(pb, vote)
}
- require.Equal(t, tc.median, pb.WeightedMedianWithAssertion())
+ if tc.panic {
+ require.Panics(t, func() { pb.WeightedMedianWithAssertion() })
+ } else {
+ require.Equal(t, tc.median, pb.WeightedMedian())
+ require.Equal(t, tc.median, pb.WeightedMedianWithAssertion())
+ }
}
}
@@ -234,21 +255,21 @@ func TestPBStandardDeviation(t *testing.T) {
[]float64{1.0, 2.0, 10.0, 100000.0},
[]int64{1, 1, 100, 1},
[]bool{true, true, true, true},
- sdk.NewDecWithPrec(4999500036300, OracleDecPrecision),
+ sdk.NewDecWithPrec(4999500036300, types.OracleDecPrecision),
},
{
// Adding fake validator doesn't change outcome
[]float64{1.0, 2.0, 10.0, 100000.0, 10000000000},
[]int64{1, 1, 100, 1, 10000},
[]bool{true, true, true, true, false},
- sdk.NewDecWithPrec(447213595075100600, OracleDecPrecision),
+ sdk.NewDecWithPrec(447213595075100600, types.OracleDecPrecision),
},
{
// Tie votes
[]float64{1.0, 2.0, 3.0, 4.0},
[]int64{1, 100, 100, 1},
[]bool{true, true, true, true},
- sdk.NewDecWithPrec(122474500, OracleDecPrecision),
+ sdk.NewDecWithPrec(122474500, types.OracleDecPrecision),
},
{
// No votes
@@ -259,9 +280,9 @@ func TestPBStandardDeviation(t *testing.T) {
},
}
- base := math.Pow10(OracleDecPrecision)
+ base := math.Pow10(types.OracleDecPrecision)
for _, tc := range tests {
- pb := ExchangeRateBallot{}
+ pb := types.ExchangeRateBallot{}
for i, input := range tc.inputs {
valAddr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address())
@@ -270,8 +291,8 @@ func TestPBStandardDeviation(t *testing.T) {
power = 0
}
- vote := NewVoteForTally(
- sdk.NewDecWithPrec(int64(input*base), int64(OracleDecPrecision)),
+ vote := types.NewVoteForTally(
+ sdk.NewDecWithPrec(int64(input*base), int64(types.OracleDecPrecision)),
core.MicroSDRDenom,
valAddr,
power,
@@ -289,12 +310,12 @@ func TestPBStandardDeviationOverflow(t *testing.T) {
exchangeRate, err := sdk.NewDecFromStr("100000000000000000000000000000000000000000000000000000000.0")
require.NoError(t, err)
- pb := ExchangeRateBallot{NewVoteForTally(
+ pb := types.ExchangeRateBallot{types.NewVoteForTally(
sdk.ZeroDec(),
core.MicroSDRDenom,
valAddr,
2,
- ), NewVoteForTally(
+ ), types.NewVoteForTally(
exchangeRate,
core.MicroSDRDenom,
valAddr,
@@ -303,3 +324,17 @@ func TestPBStandardDeviationOverflow(t *testing.T) {
require.Equal(t, sdk.ZeroDec(), pb.StandardDeviation(pb.WeightedMedianWithAssertion()))
}
+
+func TestNewClaim(t *testing.T) {
+ power := int64(10)
+ weight := int64(11)
+ winCount := int64(1)
+ addr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address().Bytes())
+ claim := types.NewClaim(power, weight, winCount, addr)
+ require.Equal(t, types.Claim{
+ Power: power,
+ Weight: weight,
+ WinCount: winCount,
+ Recipient: addr,
+ }, claim)
+}
diff --git a/x/oracle/types/denom_test.go b/x/oracle/types/denom_test.go
new file mode 100644
index 00000000..38b402da
--- /dev/null
+++ b/x/oracle/types/denom_test.go
@@ -0,0 +1,34 @@
+package types_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ "github.com/terra-money/core/x/oracle/types"
+
+ sdk "github.com/cosmos/cosmos-sdk/types"
+)
+
+func Test_DenomList(t *testing.T) {
+ denoms := types.DenomList{
+ types.Denom{
+ Name: "denom1",
+ TobinTax: sdk.NewDec(100),
+ },
+ types.Denom{
+ Name: "denom2",
+ TobinTax: sdk.NewDec(200),
+ },
+ types.Denom{
+ Name: "denom3",
+ TobinTax: sdk.NewDec(300),
+ },
+ }
+
+ require.False(t, denoms[0].Equal(&denoms[1]))
+ require.True(t, denoms[0].Equal(&denoms[0]))
+ require.Equal(t, "name: denom1\ntobin_tax: \"100.000000000000000000\"\n", denoms[0].String())
+ require.Equal(t, "name: denom2\ntobin_tax: \"200.000000000000000000\"\n", denoms[1].String())
+ require.Equal(t, "name: denom3\ntobin_tax: \"300.000000000000000000\"\n", denoms[2].String())
+ require.Equal(t, "name: denom1\ntobin_tax: \"100.000000000000000000\"\n\nname: denom2\ntobin_tax: \"200.000000000000000000\"\n\nname: denom3\ntobin_tax: \"300.000000000000000000\"", denoms.String())
+}
diff --git a/x/oracle/types/genesis.go b/x/oracle/types/genesis.go
index 4eb6493f..80eab941 100644
--- a/x/oracle/types/genesis.go
+++ b/x/oracle/types/genesis.go
@@ -28,15 +28,13 @@ func NewGenesisState(
// DefaultGenesisState - default GenesisState used by columbus-2
func DefaultGenesisState() *GenesisState {
- return &GenesisState{
- Params: DefaultParams(),
- ExchangeRates: []ExchangeRateTuple{},
- FeederDelegations: []FeederDelegation{},
- MissCounters: []MissCounter{},
- AggregateExchangeRatePrevotes: []AggregateExchangeRatePrevote{},
- AggregateExchangeRateVotes: []AggregateExchangeRateVote{},
- TobinTaxes: []TobinTax{},
- }
+ return NewGenesisState(DefaultParams(),
+ []ExchangeRateTuple{},
+ []FeederDelegation{},
+ []MissCounter{},
+ []AggregateExchangeRatePrevote{},
+ []AggregateExchangeRateVote{},
+ []TobinTax{})
}
// ValidateGenesis validates the oracle genesis state
diff --git a/x/oracle/types/genesis_test.go b/x/oracle/types/genesis_test.go
index 48a371d0..0fb5ca7a 100644
--- a/x/oracle/types/genesis_test.go
+++ b/x/oracle/types/genesis_test.go
@@ -1,15 +1,27 @@
-package types
+package types_test
import (
+ "encoding/json"
"testing"
"github.com/stretchr/testify/require"
+ "github.com/terra-money/core/app"
+ "github.com/terra-money/core/x/oracle/types"
)
func TestGenesisValidation(t *testing.T) {
- genState := DefaultGenesisState()
- require.NoError(t, ValidateGenesis(genState))
+ genState := types.DefaultGenesisState()
+ require.NoError(t, types.ValidateGenesis(genState))
genState.Params.VotePeriod = 0
- require.Error(t, ValidateGenesis(genState))
+ require.Error(t, types.ValidateGenesis(genState))
+}
+
+func TestGetGenesisStateFromAppState(t *testing.T) {
+ cdc := app.MakeEncodingConfig().Marshaler
+ appState := make(map[string]json.RawMessage)
+
+ defaultGenesisState := types.DefaultGenesisState()
+ appState[types.ModuleName] = cdc.MustMarshalJSON(defaultGenesisState)
+ require.Equal(t, *defaultGenesisState, *types.GetGenesisStateFromAppState(cdc, appState))
}
diff --git a/x/oracle/types/hash_test.go b/x/oracle/types/hash_test.go
index 8e3995d2..3b36e7bd 100644
--- a/x/oracle/types/hash_test.go
+++ b/x/oracle/types/hash_test.go
@@ -1,4 +1,4 @@
-package types
+package types_test
import (
"encoding/hex"
@@ -6,6 +6,8 @@ import (
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
+ "github.com/terra-money/core/x/oracle/types"
+
sdk "github.com/cosmos/cosmos-sdk/types"
"testing"
@@ -16,18 +18,18 @@ func TestAggregateVoteHash(t *testing.T) {
sdk.AccAddress([]byte("addr1_______________")),
}
- aggregateVoteHash := GetAggregateVoteHash("salt", "100ukrw,200uusd", sdk.ValAddress(addrs[0]))
+ aggregateVoteHash := types.GetAggregateVoteHash("salt", "100ukrw,200uusd", sdk.ValAddress(addrs[0]))
hexStr := hex.EncodeToString(aggregateVoteHash)
- aggregateVoteHashRes, err := AggregateVoteHashFromHexString(hexStr)
+ aggregateVoteHashRes, err := types.AggregateVoteHashFromHexString(hexStr)
require.NoError(t, err)
require.Equal(t, aggregateVoteHash, aggregateVoteHashRes)
require.True(t, aggregateVoteHash.Equal(aggregateVoteHash))
- require.True(t, AggregateVoteHash([]byte{}).Empty())
+ require.True(t, types.AggregateVoteHash([]byte{}).Empty())
got, _ := yaml.Marshal(&aggregateVoteHash)
require.Equal(t, aggregateVoteHash.String()+"\n", string(got))
- res := AggregateVoteHash{}
+ res := types.AggregateVoteHash{}
testMarshal(t, &aggregateVoteHash, &res, aggregateVoteHash.MarshalJSON, (&res).UnmarshalJSON)
testMarshal(t, &aggregateVoteHash, &res, aggregateVoteHash.Marshal, (&res).Unmarshal)
}
diff --git a/x/oracle/types/msgs_test.go b/x/oracle/types/msgs_test.go
index d8497e11..9fe7a17a 100644
--- a/x/oracle/types/msgs_test.go
+++ b/x/oracle/types/msgs_test.go
@@ -1,9 +1,11 @@
-package types
+package types_test
import (
+ "math/rand"
"testing"
core "github.com/terra-money/core/types"
+ "github.com/terra-money/core/x/oracle/types"
"github.com/stretchr/testify/require"
@@ -28,7 +30,7 @@ func TestMsgFeederDelegation(t *testing.T) {
}
for i, tc := range tests {
- msg := NewMsgDelegateFeedConsent(tc.delegator, tc.delegate)
+ msg := types.NewMsgDelegateFeedConsent(tc.delegator, tc.delegate)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
} else {
@@ -43,10 +45,10 @@ func TestMsgAggregateExchangeRatePrevote(t *testing.T) {
}
exchangeRates := sdk.DecCoins{sdk.NewDecCoinFromDec(core.MicroSDRDenom, sdk.OneDec()), sdk.NewDecCoinFromDec(core.MicroKRWDenom, sdk.NewDecWithPrec(32121, 1))}
- bz := GetAggregateVoteHash("1", exchangeRates.String(), sdk.ValAddress(addrs[0]))
+ bz := types.GetAggregateVoteHash("1", exchangeRates.String(), sdk.ValAddress(addrs[0]))
tests := []struct {
- hash AggregateVoteHash
+ hash types.AggregateVoteHash
exchangeRates sdk.DecCoins
voter sdk.AccAddress
expectPass bool
@@ -54,11 +56,11 @@ func TestMsgAggregateExchangeRatePrevote(t *testing.T) {
{bz, exchangeRates, addrs[0], true},
{bz[1:], exchangeRates, addrs[0], false},
{bz, exchangeRates, sdk.AccAddress{}, false},
- {AggregateVoteHash{}, exchangeRates, addrs[0], false},
+ {types.AggregateVoteHash{}, exchangeRates, addrs[0], false},
}
for i, tc := range tests {
- msg := NewMsgAggregateExchangeRatePrevote(tc.hash, tc.voter, sdk.ValAddress(tc.voter))
+ msg := types.NewMsgAggregateExchangeRatePrevote(tc.hash, tc.voter, sdk.ValAddress(tc.voter))
if tc.expectPass {
require.NoError(t, msg.ValidateBasic(), "test: %v", i)
} else {
@@ -79,20 +81,24 @@ func TestMsgAggregateExchangeRateVote(t *testing.T) {
tests := []struct {
voter sdk.AccAddress
+ validator sdk.ValAddress
salt string
exchangeRates string
expectPass bool
}{
- {addrs[0], "123", exchangeRates, true},
- {addrs[0], "123", invalidExchangeRates, false},
- {addrs[0], "123", abstainExchangeRates, true},
- {addrs[0], "123", overFlowExchangeRates, false},
- {sdk.AccAddress{}, "123", exchangeRates, false},
- {addrs[0], "", exchangeRates, false},
+ {addrs[0], sdk.ValAddress(addrs[0]), "123", exchangeRates, true},
+ {addrs[0], sdk.ValAddress(addrs[0]), "123", invalidExchangeRates, false},
+ {addrs[0], sdk.ValAddress(addrs[0]), "123", abstainExchangeRates, true},
+ {addrs[0], sdk.ValAddress(addrs[0]), "123", overFlowExchangeRates, false},
+ {sdk.AccAddress{}, sdk.ValAddress(addrs[0]), "123", exchangeRates, false},
+ {addrs[0], sdk.ValAddress(addrs[0]), "123", "", false},
+ {addrs[0], sdk.ValAddress(addrs[0]), "", randSeq(4097), false},
+ {addrs[0], sdk.ValAddress{}, "123", abstainExchangeRates, false},
+ {addrs[0], sdk.ValAddress(addrs[0]), "", abstainExchangeRates, false},
}
for i, tc := range tests {
- msg := NewMsgAggregateExchangeRateVote(tc.salt, tc.exchangeRates, tc.voter, sdk.ValAddress(tc.voter))
+ msg := types.NewMsgAggregateExchangeRateVote(tc.salt, tc.exchangeRates, tc.voter, tc.validator)
if tc.expectPass {
require.Nil(t, msg.ValidateBasic(), "test: %v", i)
} else {
@@ -100,3 +106,13 @@ func TestMsgAggregateExchangeRateVote(t *testing.T) {
}
}
}
+
+var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
+func randSeq(n int) string {
+ b := make([]rune, n)
+ for i := range b {
+ b[i] = letters[rand.Intn(len(letters))]
+ }
+ return string(b)
+}
diff --git a/x/oracle/types/params_test.go b/x/oracle/types/params_test.go
index 0a4c65a3..e2a8b657 100644
--- a/x/oracle/types/params_test.go
+++ b/x/oracle/types/params_test.go
@@ -1,15 +1,18 @@
-package types
+package types_test
import (
+ "bytes"
"testing"
"github.com/stretchr/testify/require"
+ "github.com/terra-money/core/x/oracle/types"
+
sdk "github.com/cosmos/cosmos-sdk/types"
)
func TestParamsEqual(t *testing.T) {
- p1 := DefaultParams()
+ p1 := types.DefaultParams()
err := p1.Validate()
require.NoError(t, err)
@@ -19,54 +22,113 @@ func TestParamsEqual(t *testing.T) {
require.Error(t, err)
// small vote threshold
- p2 := DefaultParams()
+ p2 := types.DefaultParams()
p2.VoteThreshold = sdk.ZeroDec()
err = p2.Validate()
require.Error(t, err)
// negative reward band
- p3 := DefaultParams()
+ p3 := types.DefaultParams()
p3.RewardBand = sdk.NewDecWithPrec(-1, 2)
err = p3.Validate()
require.Error(t, err)
// negative slash fraction
- p4 := DefaultParams()
+ p4 := types.DefaultParams()
p4.SlashFraction = sdk.NewDec(-1)
err = p4.Validate()
require.Error(t, err)
// negative min valid per window
- p5 := DefaultParams()
+ p5 := types.DefaultParams()
p5.MinValidPerWindow = sdk.NewDec(-1)
err = p5.Validate()
require.Error(t, err)
// small slash window
- p6 := DefaultParams()
+ p6 := types.DefaultParams()
p6.SlashWindow = 0
err = p6.Validate()
require.Error(t, err)
// small distribution window
- p7 := DefaultParams()
+ p7 := types.DefaultParams()
p7.RewardDistributionWindow = 0
err = p7.Validate()
require.Error(t, err)
// non-positive tobin tax
- p8 := DefaultParams()
- p8.Whitelist[0].TobinTax = sdk.NewDec(-1)
+ p8 := types.DefaultParams()
+ p8.Whitelist[0].Name = ""
err = p8.Validate()
require.Error(t, err)
- // empty name
- p9 := DefaultParams()
- p9.Whitelist[0].Name = ""
+ // invalid name tobin tax
+ p9 := types.DefaultParams()
+ p9.Whitelist[0].TobinTax = sdk.NewDec(-1)
err = p9.Validate()
require.Error(t, err)
- p10 := DefaultParams()
- require.NotNil(t, p10.ParamSetPairs())
- require.NotNil(t, p10.String())
+ // empty name
+ p10 := types.DefaultParams()
+ p10.Whitelist[0].Name = ""
+ err = p10.Validate()
+ require.Error(t, err)
+
+ p11 := types.DefaultParams()
+ require.NotNil(t, p11.ParamSetPairs())
+ require.NotNil(t, p11.String())
+}
+
+func TestValidate(t *testing.T) {
+ p1 := types.DefaultParams()
+ pairs := p1.ParamSetPairs()
+ for _, pair := range pairs {
+ switch {
+ case bytes.Compare(types.KeyVotePeriod, pair.Key) == 0 ||
+ bytes.Compare(types.KeyRewardDistributionWindow, pair.Key) == 0 ||
+ bytes.Compare(types.KeySlashWindow, pair.Key) == 0:
+ require.NoError(t, pair.ValidatorFn(uint64(1)))
+ require.Error(t, pair.ValidatorFn("invalid"))
+ require.Error(t, pair.ValidatorFn(uint64(0)))
+ case bytes.Compare(types.KeyVoteThreshold, pair.Key) == 0:
+ require.NoError(t, pair.ValidatorFn(sdk.NewDecWithPrec(33, 2)))
+ require.Error(t, pair.ValidatorFn("invalid"))
+ require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(32, 2)))
+ require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(101, 2)))
+ case bytes.Compare(types.KeyRewardBand, pair.Key) == 0 ||
+ bytes.Compare(types.KeySlashFraction, pair.Key) == 0 ||
+ bytes.Compare(types.KeyMinValidPerWindow, pair.Key) == 0:
+ require.NoError(t, pair.ValidatorFn(sdk.NewDecWithPrec(7, 2)))
+ require.Error(t, pair.ValidatorFn("invalid"))
+ require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(-1, 2)))
+ require.Error(t, pair.ValidatorFn(sdk.NewDecWithPrec(101, 2)))
+ case bytes.Compare(types.KeyWhitelist, pair.Key) == 0:
+ require.NoError(t, pair.ValidatorFn(types.DenomList{
+ {
+ Name: "denom",
+ TobinTax: sdk.NewDecWithPrec(10, 2),
+ },
+ }))
+ require.Error(t, pair.ValidatorFn("invalid"))
+ require.Error(t, pair.ValidatorFn(types.DenomList{
+ {
+ Name: "",
+ TobinTax: sdk.NewDecWithPrec(10, 2),
+ },
+ }))
+ require.Error(t, pair.ValidatorFn(types.DenomList{
+ {
+ Name: "denom",
+ TobinTax: sdk.NewDecWithPrec(101, 2),
+ },
+ }))
+ require.Error(t, pair.ValidatorFn(types.DenomList{
+ {
+ Name: "denom",
+ TobinTax: sdk.NewDecWithPrec(-1, 2),
+ },
+ }))
+ }
+ }
}
diff --git a/x/oracle/types/vote_test.go b/x/oracle/types/vote_test.go
index df50bb21..ad21dbb3 100644
--- a/x/oracle/types/vote_test.go
+++ b/x/oracle/types/vote_test.go
@@ -1,29 +1,30 @@
-package types
+package types_test
import (
"testing"
"github.com/stretchr/testify/require"
+ "github.com/terra-money/core/x/oracle/types"
)
func TestParseExchangeRateTuples(t *testing.T) {
valid := "123.0uluna,123.123ukrw"
- _, err := ParseExchangeRateTuples(valid)
+ _, err := types.ParseExchangeRateTuples(valid)
require.NoError(t, err)
duplicatedDenom := "100.0uluna,123.123ukrw,121233.123ukrw"
- _, err = ParseExchangeRateTuples(duplicatedDenom)
+ _, err = types.ParseExchangeRateTuples(duplicatedDenom)
require.Error(t, err)
invalidCoins := "123.123"
- _, err = ParseExchangeRateTuples(invalidCoins)
+ _, err = types.ParseExchangeRateTuples(invalidCoins)
require.Error(t, err)
invalidCoinsWithValid := "123.0uluna,123.1"
- _, err = ParseExchangeRateTuples(invalidCoinsWithValid)
+ _, err = types.ParseExchangeRateTuples(invalidCoinsWithValid)
require.Error(t, err)
abstainCoinsWithValid := "0.0uluna,123.1ukrw"
- _, err = ParseExchangeRateTuples(abstainCoinsWithValid)
+ _, err = types.ParseExchangeRateTuples(abstainCoinsWithValid)
require.NoError(t, err)
}
diff --git a/x/wasm/keeper/legacy_querier_test.go b/x/wasm/keeper/legacy_querier_test.go
index f792fb47..555fe1bf 100644
--- a/x/wasm/keeper/legacy_querier_test.go
+++ b/x/wasm/keeper/legacy_querier_test.go
@@ -81,6 +81,20 @@ func TestLegacyContractState(t *testing.T) {
_, err = querier(ctx, []string{types.QueryContractStore}, abci.RequestQuery{Data: []byte(bz)})
require.Error(t, err)
+
+ bz, err = input.Cdc.MarshalJSON(types.NewQueryCodeIDParams(contractID))
+ _, err = querier(ctx, []string{types.QueryGetByteCode}, abci.RequestQuery{Data: []byte(bz)})
+ require.NoError(t, err)
+
+ _, err = querier(ctx, []string{types.QueryGetCodeInfo}, abci.RequestQuery{Data: []byte(bz)})
+ require.NoError(t, err)
+
+ bz, err = input.Cdc.MarshalJSON(types.NewQueryContractAddressParams(addr))
+ _, err = querier(ctx, []string{types.QueryGetContractInfo}, abci.RequestQuery{Data: []byte(bz)})
+ require.NoError(t, err)
+
+ _, err = querier(ctx, []string{types.QueryParameters}, abci.RequestQuery{})
+ require.NoError(t, err)
}
func TestLegacyParams(t *testing.T) {
diff --git a/x/wasm/keeper/querier_test.go b/x/wasm/keeper/querier_test.go
index 4df4eb87..62612351 100644
--- a/x/wasm/keeper/querier_test.go
+++ b/x/wasm/keeper/querier_test.go
@@ -129,3 +129,59 @@ func TestQueryMultipleGoroutines(t *testing.T) {
}
wg.Wait()
}
+
+func TestQueryCodeAndContractInfo(t *testing.T) {
+ input := CreateTestInput(t)
+ goCtx := sdk.WrapSDKContext(input.Ctx)
+ ctx, accKeeper, bankKeeper, keeper := input.Ctx, input.AccKeeper, input.BankKeeper, input.WasmKeeper
+
+ deposit := sdk.NewCoins(sdk.NewInt64Coin("denom", 100000))
+ topUp := sdk.NewCoins(sdk.NewInt64Coin("denom", 5000))
+ creator := createFakeFundedAccount(ctx, accKeeper, bankKeeper, deposit.Add(deposit...))
+ anyAddr := createFakeFundedAccount(ctx, accKeeper, bankKeeper, topUp)
+
+ wasmCode, err := ioutil.ReadFile("./testdata/hackatom.wasm")
+ require.NoError(t, err)
+
+ contractID, err := keeper.StoreCode(ctx, creator, wasmCode)
+ require.NoError(t, err)
+
+ _, _, bob := keyPubAddr()
+ initMsg := HackatomExampleInitMsg{
+ Verifier: anyAddr,
+ Beneficiary: bob,
+ }
+ initMsgBz, err := json.Marshal(initMsg)
+ require.NoError(t, err)
+
+ addr, _, err := keeper.InstantiateContract(ctx, contractID, creator, sdk.AccAddress{}, initMsgBz, deposit)
+ require.NoError(t, err)
+
+ contractModel := []types.Model{
+ {Key: []byte("foo"), Value: []byte(`"bar"`)},
+ {Key: []byte{0x0, 0x1}, Value: []byte(`{"count":8}`)},
+ }
+
+ keeper.SetContractStore(ctx, addr, contractModel)
+
+ querier := NewQuerier(keeper)
+
+ res, err := querier.CodeInfo(goCtx, &types.QueryCodeInfoRequest{CodeId: contractID})
+ require.NoError(t, err)
+ require.Equal(t, creator.String(), res.GetCodeInfo().Creator)
+ require.Equal(t, contractID, res.GetCodeInfo().CodeID)
+
+ res2, err := querier.ByteCode(goCtx, &types.QueryByteCodeRequest{CodeId: contractID})
+ require.NoError(t, err)
+ require.Equal(t, res2.GetByteCode(), wasmCode)
+
+ res3, err := querier.ContractInfo(goCtx, &types.QueryContractInfoRequest{ContractAddress: addr.String()})
+ require.NoError(t, err)
+ require.Equal(t, addr.String(), res3.GetContractInfo().Address)
+ require.Equal(t, "", res3.GetContractInfo().Admin)
+ require.Equal(t, creator.String(), res3.GetContractInfo().Creator)
+ require.Equal(t, contractID, res3.GetContractInfo().CodeID)
+ queriedInitMsg, err := res3.GetContractInfo().InitMsg.MarshalJSON()
+ require.NoError(t, err)
+ require.Equal(t, initMsgBz, queriedInitMsg)
+}