From 07352ebed0671fd25b4f743e5ccc13acb7a337c2 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 26 Apr 2024 11:10:21 +0800 Subject: [PATCH 1/5] vote extension to proto --- proto/kujira/oracle/oracle.proto | 7 + x/oracle/abci/proposal.go | 8 +- x/oracle/abci/proposal_test.go | 160 +++++++++----- x/oracle/abci/vote_extensions.go | 31 +-- x/oracle/abci/vote_extensions_test.go | 37 +++- x/oracle/types/oracle.pb.go | 302 ++++++++++++++++++++++---- 6 files changed, 433 insertions(+), 112 deletions(-) diff --git a/proto/kujira/oracle/oracle.proto b/proto/kujira/oracle/oracle.proto index 1b9022b0..433339d9 100644 --- a/proto/kujira/oracle/oracle.proto +++ b/proto/kujira/oracle/oracle.proto @@ -71,3 +71,10 @@ message ExchangeRateTuple { (gogoproto.nullable) = false ]; } + +message VoteExtension { + int64 height = 1; + repeated ExchangeRateTuple prices = 2 [ + (gogoproto.nullable) = false + ]; +} diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index 9169fad6..85e4e93a 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -248,13 +248,15 @@ func (h *ProposalHandler) GetBallotByDenom(ci abci.ExtendedCommitInfo, validator if ok { power := claim.Power - var voteExt OracleVoteExtension - if err := json.Unmarshal(v.VoteExtension, &voteExt); err != nil { + var voteExt types.VoteExtension + if err := voteExt.Unmarshal(v.VoteExtension); err != nil { h.logger.Error("failed to decode vote extension", "err", err, "validator", fmt.Sprintf("%x", v.Validator.Address)) return votes } - for base, price := range voteExt.Prices { + for _, tuple := range voteExt.Prices { + base := tuple.Denom + price := tuple.ExchangeRate tmpPower := power if !price.IsPositive() { // Make the power of abstain vote zero diff --git a/x/oracle/abci/proposal_test.go b/x/oracle/abci/proposal_test.go index 49bb7e4b..bda8c8fe 100644 --- a/x/oracle/abci/proposal_test.go +++ b/x/oracle/abci/proposal_test.go @@ -80,23 +80,35 @@ func TestGetBallotByDenom(t *testing.T) { power := int64(100) // organize votes by denom - voteExt1 := abci.OracleVoteExtension{ + voteExt1 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25000), - "ETH": math.LegacyNewDec(2200), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25000), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2200), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25030), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2180), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := voteExt1.Marshal() require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := voteExt2.Marshal() require.NoError(t, err) consAddrMap := map[string]sdk.ValAddress{ @@ -159,23 +171,35 @@ func TestComputeStakeWeightedPricesAndMissMap(t *testing.T) { input, h := SetupTest(t) // organize votes by denom - voteExt1 := abci.OracleVoteExtension{ + voteExt1 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25000), - "ETH": math.LegacyNewDec(2200), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25000), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2200), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25030), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2180), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := voteExt1.Marshal() require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := voteExt2.Marshal() require.NoError(t, err) params := types.DefaultParams() @@ -435,23 +459,35 @@ func TestPrepareProposal(t *testing.T) { require.Error(t, err) // Valid vote extension data - voteExt1 := abci.OracleVoteExtension{ + voteExt1 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25000), - "ETH": math.LegacyNewDec(2200), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25000), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2200), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25030), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2180), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := voteExt1.Marshal() require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := voteExt2.Marshal() require.NoError(t, err) marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { var buf bytes.Buffer @@ -576,23 +612,35 @@ func TestProcessProposal(t *testing.T) { input.Ctx = input.Ctx.WithConsensusParams(consParams) // Valid vote extension data - voteExt1 := abci.OracleVoteExtension{ + voteExt1 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25000), - "ETH": math.LegacyNewDec(2200), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25000), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2200), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25030), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2180), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := voteExt1.Marshal() require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := voteExt2.Marshal() require.NoError(t, err) marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { var buf bytes.Buffer @@ -779,23 +827,35 @@ func TestPreBlocker(t *testing.T) { input.Ctx = input.Ctx.WithConsensusParams(consParams) // Valid vote extension data - voteExt1 := abci.OracleVoteExtension{ + voteExt1 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25000), - "ETH": math.LegacyNewDec(2200), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25000), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2200), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(25030), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyNewDec(2180), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := voteExt1.Marshal() require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := voteExt2.Marshal() require.NoError(t, err) marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { var buf bytes.Buffer diff --git a/x/oracle/abci/vote_extensions.go b/x/oracle/abci/vote_extensions.go index 393bb751..b093ac80 100644 --- a/x/oracle/abci/vote_extensions.go +++ b/x/oracle/abci/vote_extensions.go @@ -10,6 +10,7 @@ import ( "cosmossdk.io/log" "cosmossdk.io/math" "github.com/Team-Kujira/core/x/oracle/keeper" + "github.com/Team-Kujira/core/x/oracle/types" abci "github.com/cometbft/cometbft/abci/types" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -32,12 +33,6 @@ func NewVoteExtHandler( } } -// OracleVoteExtension defines the canonical vote extension structure. -type OracleVoteExtension struct { - Height int64 - Prices map[string]math.LegacyDec -} - type PricesResponse struct { Prices map[string]math.LegacyDec `json:"prices"` } @@ -49,13 +44,13 @@ func (h *VoteExtHandler) ExtendVoteHandler(oracleConfig OracleConfig) sdk.Extend h.logger.Info("computing oracle prices for vote extension", "height", req.Height, "time", h.lastPriceSyncTS, "endpoint", oracleConfig.Endpoint) - emptyVoteExt := OracleVoteExtension{ + emptyVoteExt := types.VoteExtension{ Height: req.Height, - Prices: map[string]math.LegacyDec{}, + Prices: []types.ExchangeRateTuple{}, } // Encode vote extension to bytes - emptyVoteExtBz, err := json.Marshal(emptyVoteExt) + emptyVoteExtBz, err := emptyVoteExt.Marshal() if err != nil { return nil, fmt.Errorf("failed to marshal vote extension: %w", err) } @@ -80,10 +75,16 @@ func (h *VoteExtHandler) ExtendVoteHandler(oracleConfig OracleConfig) sdk.Extend return &abci.ResponseExtendVote{VoteExtension: emptyVoteExtBz}, nil } - computedPrices := prices.Prices + computedPrices := []types.ExchangeRateTuple{} + for denom, rate := range prices.Prices { + computedPrices = append(computedPrices, types.ExchangeRateTuple{ + Denom: denom, + ExchangeRate: rate, + }) + } // produce a canonical vote extension - voteExt := OracleVoteExtension{ + voteExt := types.VoteExtension{ Height: req.Height, Prices: computedPrices, } @@ -91,7 +92,7 @@ func (h *VoteExtHandler) ExtendVoteHandler(oracleConfig OracleConfig) sdk.Extend h.logger.Info("computed prices", "prices", computedPrices) // Encode vote extension to bytes - bz, err := json.Marshal(voteExt) + bz, err := voteExt.Marshal() if err != nil { return nil, fmt.Errorf("failed to marshal vote extension: %w", err) } @@ -102,13 +103,13 @@ func (h *VoteExtHandler) ExtendVoteHandler(oracleConfig OracleConfig) sdk.Extend func (h *VoteExtHandler) VerifyVoteExtensionHandler(_ OracleConfig) sdk.VerifyVoteExtensionHandler { return func(ctx sdk.Context, req *abci.RequestVerifyVoteExtension) (*abci.ResponseVerifyVoteExtension, error) { - var voteExt OracleVoteExtension + var voteExt types.VoteExtension if len(req.VoteExtension) == 0 { return &abci.ResponseVerifyVoteExtension{Status: abci.ResponseVerifyVoteExtension_ACCEPT}, nil } - err := json.Unmarshal(req.VoteExtension, &voteExt) + err := voteExt.Unmarshal(req.VoteExtension) if err != nil { // NOTE: It is safe to return an error as the Cosmos SDK will capture all // errors, log them, and reject the proposal. @@ -129,6 +130,6 @@ func (h *VoteExtHandler) VerifyVoteExtensionHandler(_ OracleConfig) sdk.VerifyVo } } -func (h *VoteExtHandler) verifyOraclePrices(_ sdk.Context, _ map[string]math.LegacyDec) error { +func (h *VoteExtHandler) verifyOraclePrices(_ sdk.Context, _ []types.ExchangeRateTuple) error { return nil } diff --git a/x/oracle/abci/vote_extensions_test.go b/x/oracle/abci/vote_extensions_test.go index 3a5d617c..f30edc0d 100644 --- a/x/oracle/abci/vote_extensions_test.go +++ b/x/oracle/abci/vote_extensions_test.go @@ -7,8 +7,10 @@ import ( "testing" "time" + "cosmossdk.io/math" "github.com/Team-Kujira/core/x/oracle/abci" "github.com/Team-Kujira/core/x/oracle/keeper" + "github.com/Team-Kujira/core/x/oracle/types" cometabci "github.com/cometbft/cometbft/abci/types" "github.com/stretchr/testify/require" ) @@ -44,7 +46,17 @@ func TestExtendVoteHandler(t *testing.T) { ProposerAddress: []byte{}, }) require.NoError(t, err) - require.Equal(t, string(res.VoteExtension), `{"Height":3,"Prices":{"BTC":"47375.706652541026694000","ETH":"2649.328939436595054949","USDT":"1.000661260343873178"}}`) + voteExt := types.VoteExtension{} + err = voteExt.Unmarshal(res.VoteExtension) + require.NoError(t, err) + require.Equal(t, voteExt.Height, int64(3)) + require.Len(t, voteExt.Prices, 3) + require.Equal(t, voteExt.Prices[0].Denom, "BTC") + require.Equal(t, voteExt.Prices[0].ExchangeRate.String(), "47375.706652541026694000") + require.Equal(t, voteExt.Prices[1].Denom, "ETH") + require.Equal(t, voteExt.Prices[1].ExchangeRate.String(), "2649.328939436595054949") + require.Equal(t, voteExt.Prices[2].Denom, "USDT") + require.Equal(t, voteExt.Prices[2].ExchangeRate.String(), "1.000661260343873178") } func TestVerifyVoteExtensionHandler(t *testing.T) { @@ -61,11 +73,30 @@ func TestVerifyVoteExtensionHandler(t *testing.T) { Endpoint: testServer.URL, }) + voteExt := types.VoteExtension{ + Height: 3, + Prices: []types.ExchangeRateTuple{ + { + Denom: "BTC", + ExchangeRate: math.LegacyMustNewDecFromStr("47375.706652541026694000"), + }, + { + Denom: "ETH", + ExchangeRate: math.LegacyMustNewDecFromStr("2649.328939436595054949"), + }, + { + Denom: "USDT", + ExchangeRate: math.LegacyMustNewDecFromStr("1.000661260343873178"), + }, + }, + } + voteExtBz, err := voteExt.Marshal() + require.NoError(t, err) // Height's same res, err := handler(input.Ctx, &cometabci.RequestVerifyVoteExtension{ Hash: []byte{}, Height: 3, - VoteExtension: []byte(`{"Height":3,"Prices":{"BTC":"47375.706652541026694000","ETH":"2649.328939436595054949","USDT":"1.000661260343873178"}}`), + VoteExtension: voteExtBz, ValidatorAddress: []byte{}, }) require.NoError(t, err) @@ -75,7 +106,7 @@ func TestVerifyVoteExtensionHandler(t *testing.T) { _, err = handler(input.Ctx, &cometabci.RequestVerifyVoteExtension{ Hash: []byte{}, Height: 2, - VoteExtension: []byte(`{"Height":3,"Prices":{"BTC":"47375.706652541026694000","ETH":"2649.328939436595054949","USDT":"1.000661260343873178"}}`), + VoteExtension: voteExtBz, ValidatorAddress: []byte{}, }) require.Error(t, err) diff --git a/x/oracle/types/oracle.pb.go b/x/oracle/types/oracle.pb.go index ae079eef..e54a510f 100644 --- a/x/oracle/types/oracle.pb.go +++ b/x/oracle/types/oracle.pb.go @@ -174,56 +174,113 @@ func (m *ExchangeRateTuple) XXX_DiscardUnknown() { var xxx_messageInfo_ExchangeRateTuple proto.InternalMessageInfo +type VoteExtension struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Prices []ExchangeRateTuple `protobuf:"bytes,2,rep,name=prices,proto3" json:"prices"` +} + +func (m *VoteExtension) Reset() { *m = VoteExtension{} } +func (m *VoteExtension) String() string { return proto.CompactTextString(m) } +func (*VoteExtension) ProtoMessage() {} +func (*VoteExtension) Descriptor() ([]byte, []int) { + return fileDescriptor_8fffe8fb5ee63325, []int{3} +} +func (m *VoteExtension) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteExtension) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteExtension.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *VoteExtension) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteExtension.Merge(m, src) +} +func (m *VoteExtension) XXX_Size() int { + return m.Size() +} +func (m *VoteExtension) XXX_DiscardUnknown() { + xxx_messageInfo_VoteExtension.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteExtension proto.InternalMessageInfo + +func (m *VoteExtension) GetHeight() int64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *VoteExtension) GetPrices() []ExchangeRateTuple { + if m != nil { + return m.Prices + } + return nil +} + func init() { proto.RegisterType((*Params)(nil), "kujira.oracle.Params") proto.RegisterType((*Denom)(nil), "kujira.oracle.Denom") proto.RegisterType((*ExchangeRateTuple)(nil), "kujira.oracle.ExchangeRateTuple") + proto.RegisterType((*VoteExtension)(nil), "kujira.oracle.VoteExtension") } func init() { proto.RegisterFile("kujira/oracle/oracle.proto", fileDescriptor_8fffe8fb5ee63325) } var fileDescriptor_8fffe8fb5ee63325 = []byte{ - // 639 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x3d, 0x6f, 0xd3, 0x40, - 0x18, 0xb6, 0x69, 0x1b, 0x9a, 0x4b, 0xd2, 0x0f, 0x13, 0x8a, 0x95, 0x4a, 0x76, 0x74, 0x08, 0x14, - 0x21, 0x61, 0xab, 0x30, 0x20, 0x02, 0x93, 0x09, 0x2c, 0x74, 0xa8, 0xac, 0x0a, 0x44, 0x17, 0x73, - 0xb1, 0x8f, 0xf8, 0xa8, 0xed, 0x0b, 0xe7, 0xcb, 0x47, 0xff, 0x01, 0x23, 0x23, 0x63, 0x07, 0x26, - 0xf8, 0x23, 0x1d, 0x3b, 0x22, 0x06, 0x83, 0xda, 0x85, 0xd9, 0xbf, 0x00, 0xf9, 0xce, 0x29, 0x09, - 0x62, 0x28, 0x4c, 0xf6, 0xf3, 0x3c, 0xef, 0xfb, 0x3c, 0xaf, 0xee, 0x0b, 0xb4, 0x0e, 0x47, 0x6f, - 0x09, 0x43, 0x36, 0x65, 0xc8, 0x8f, 0x70, 0xf9, 0xb1, 0x86, 0x8c, 0x72, 0xaa, 0x35, 0xa4, 0x66, - 0x49, 0xb2, 0xd5, 0x1c, 0xd0, 0x01, 0x15, 0x8a, 0x5d, 0xfc, 0xc9, 0xa2, 0x96, 0xe1, 0xd3, 0x34, - 0xa6, 0xa9, 0xdd, 0x47, 0x29, 0xb6, 0xc7, 0x3b, 0x7d, 0xcc, 0xd1, 0x8e, 0xed, 0x53, 0x92, 0x48, - 0x1d, 0x7e, 0xaa, 0x80, 0xca, 0x1e, 0x62, 0x28, 0x4e, 0xb5, 0x07, 0xa0, 0x36, 0xa6, 0x1c, 0x7b, - 0x43, 0xcc, 0x08, 0x0d, 0x74, 0xb5, 0xad, 0x76, 0x96, 0x9d, 0xad, 0x3c, 0x33, 0xb5, 0x23, 0x14, - 0x47, 0x5d, 0x38, 0x27, 0x42, 0x17, 0x14, 0x68, 0x4f, 0x00, 0xcd, 0x07, 0x6b, 0x42, 0xe3, 0x21, - 0xc3, 0x69, 0x48, 0xa3, 0x40, 0xbf, 0xd2, 0x56, 0x3b, 0x55, 0xe7, 0xf1, 0x49, 0x66, 0x2a, 0xdf, - 0x32, 0x73, 0x5b, 0xce, 0x90, 0x06, 0x87, 0x16, 0xa1, 0x76, 0x8c, 0x78, 0x68, 0xed, 0xe2, 0x01, - 0xf2, 0x8f, 0x7a, 0xd8, 0xcf, 0x33, 0xf3, 0xfa, 0x9c, 0xfd, 0x85, 0x05, 0x74, 0x1b, 0x05, 0xb1, - 0x3f, 0xc3, 0xda, 0x6b, 0xd0, 0x88, 0xd1, 0xd4, 0x0b, 0xf0, 0x98, 0x20, 0x4e, 0x68, 0xa2, 0x2f, - 0x89, 0x8c, 0x47, 0x97, 0xcb, 0x68, 0xca, 0x8c, 0x05, 0x07, 0xe8, 0xd6, 0x63, 0x34, 0xed, 0xcd, - 0xa0, 0xf6, 0x04, 0xac, 0x33, 0xfc, 0x6e, 0x44, 0x18, 0x0e, 0xbc, 0x00, 0x27, 0x34, 0x4e, 0xf5, - 0xe5, 0xf6, 0x52, 0xa7, 0xea, 0xb4, 0xf2, 0xcc, 0xdc, 0x92, 0x06, 0x7f, 0x14, 0x40, 0x77, 0x6d, - 0xc6, 0xf4, 0x04, 0x51, 0xac, 0x45, 0x1a, 0xa1, 0x34, 0xf4, 0xde, 0x30, 0xe4, 0x8b, 0x39, 0x57, - 0xfe, 0x63, 0x2d, 0x16, 0x2d, 0xa0, 0xdb, 0x10, 0xc4, 0xb3, 0x12, 0x6b, 0x5d, 0x50, 0x97, 0x15, - 0x13, 0x92, 0x04, 0x74, 0xa2, 0x57, 0xc4, 0x56, 0xdd, 0xc8, 0x33, 0xf3, 0xda, 0x7c, 0xbf, 0x54, - 0xa1, 0x5b, 0x13, 0xf0, 0xa5, 0x40, 0x5a, 0x0a, 0x9a, 0x31, 0x49, 0xbc, 0x31, 0x8a, 0x48, 0x50, - 0xec, 0xe6, 0xcc, 0xe3, 0xaa, 0x18, 0xd3, 0xb9, 0xdc, 0x98, 0xdb, 0xe5, 0x72, 0xfe, 0xc5, 0x08, - 0xba, 0x9b, 0x31, 0x49, 0x5e, 0x14, 0xec, 0x1e, 0x66, 0x65, 0xe8, 0x01, 0xa8, 0x31, 0x3c, 0x41, - 0x2c, 0xf0, 0xfa, 0x28, 0x09, 0xf4, 0x55, 0x91, 0xf5, 0xf0, 0x72, 0x59, 0xda, 0x6c, 0xe5, 0x2f, - 0xfa, 0xa1, 0x0b, 0x24, 0x72, 0x50, 0x12, 0x68, 0xaf, 0x40, 0x75, 0x12, 0x12, 0x8e, 0x23, 0x92, - 0x72, 0xbd, 0xda, 0x5e, 0xea, 0xd4, 0xee, 0x35, 0xad, 0x85, 0xab, 0x61, 0x89, 0xbd, 0x71, 0x6e, - 0x15, 0x79, 0x79, 0x66, 0x6e, 0x48, 0xc3, 0x8b, 0x26, 0xf8, 0xf9, 0xbb, 0x59, 0x15, 0x25, 0xbb, - 0x24, 0xe5, 0xee, 0x6f, 0xb7, 0xee, 0xea, 0xc7, 0x63, 0x53, 0xf9, 0x79, 0x6c, 0xaa, 0xb0, 0x0b, - 0x56, 0x44, 0x85, 0x76, 0x13, 0x2c, 0x27, 0x28, 0xc6, 0xe2, 0x76, 0x54, 0x9d, 0xf5, 0x3c, 0x33, - 0x6b, 0xd2, 0xae, 0x60, 0xa1, 0x2b, 0xc4, 0x6e, 0xfd, 0xfd, 0xb1, 0xa9, 0x94, 0xbd, 0x0a, 0xfc, - 0xa2, 0x82, 0xcd, 0xa7, 0x53, 0x3f, 0x44, 0xc9, 0x00, 0xbb, 0x88, 0xe3, 0xfd, 0xd1, 0x30, 0xc2, - 0xda, 0x6d, 0xb0, 0x22, 0xce, 0x50, 0xe9, 0xb4, 0x91, 0x67, 0x66, 0x5d, 0x3a, 0x09, 0x1a, 0xba, - 0x52, 0x2e, 0xce, 0x3d, 0x2e, 0x9b, 0x3d, 0x86, 0x38, 0x2e, 0xef, 0xd6, 0xbf, 0x9d, 0xfb, 0x05, - 0x07, 0xe8, 0xd6, 0xf1, 0xdc, 0x38, 0x8b, 0xd3, 0x3a, 0xbd, 0x93, 0x33, 0x43, 0x3d, 0x3d, 0x33, - 0xd4, 0x1f, 0x67, 0x86, 0xfa, 0xe1, 0xdc, 0x50, 0x4e, 0xcf, 0x0d, 0xe5, 0xeb, 0xb9, 0xa1, 0x1c, - 0xdc, 0x19, 0x10, 0x1e, 0x8e, 0xfa, 0x96, 0x4f, 0x63, 0x7b, 0x1f, 0xa3, 0xf8, 0xee, 0x73, 0xf9, - 0x36, 0xf9, 0x94, 0x61, 0x7b, 0x3a, 0x7b, 0xa2, 0xf8, 0xd1, 0x10, 0xa7, 0xfd, 0x8a, 0x78, 0x5d, - 0xee, 0xff, 0x0a, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xcd, 0x96, 0xa6, 0xc0, 0x04, 0x00, 0x00, + // 693 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x3d, 0x6f, 0x13, 0x4b, + 0x14, 0xf5, 0xc6, 0x8e, 0x5f, 0x3c, 0xb6, 0xf3, 0xb1, 0xcf, 0x2f, 0x6f, 0xe5, 0x48, 0x5e, 0x6b, + 0x10, 0xc8, 0x42, 0xc2, 0xab, 0x40, 0x81, 0x30, 0x88, 0x62, 0x71, 0x68, 0x48, 0x11, 0x8d, 0xa2, + 0x20, 0xd2, 0x98, 0xf1, 0xee, 0xe0, 0x1d, 0xe2, 0xdd, 0x31, 0x33, 0xe3, 0x8f, 0xfc, 0x03, 0x4a, + 0x4a, 0xca, 0x14, 0x54, 0xf0, 0x47, 0x52, 0xa6, 0x44, 0x14, 0x0b, 0x4a, 0x1a, 0x6a, 0xff, 0x02, + 0xb4, 0x33, 0xeb, 0x60, 0x07, 0x8a, 0x40, 0x65, 0x9f, 0x7b, 0xee, 0x3d, 0xf7, 0xec, 0x9d, 0x3b, + 0x03, 0xaa, 0x47, 0xc3, 0xd7, 0x94, 0x63, 0x87, 0x71, 0xec, 0xf5, 0x49, 0xfa, 0xd3, 0x1c, 0x70, + 0x26, 0x99, 0x59, 0xd6, 0x5c, 0x53, 0x07, 0xab, 0x95, 0x1e, 0xeb, 0x31, 0xc5, 0x38, 0xc9, 0x3f, + 0x9d, 0x54, 0xad, 0x79, 0x4c, 0x84, 0x4c, 0x38, 0x5d, 0x2c, 0x88, 0x33, 0xda, 0xee, 0x12, 0x89, + 0xb7, 0x1d, 0x8f, 0xd1, 0x48, 0xf3, 0xf0, 0x43, 0x1e, 0xe4, 0xf7, 0x30, 0xc7, 0xa1, 0x30, 0xef, + 0x83, 0xe2, 0x88, 0x49, 0xd2, 0x19, 0x10, 0x4e, 0x99, 0x6f, 0x19, 0x75, 0xa3, 0x91, 0x73, 0x37, + 0xa7, 0xb1, 0x6d, 0x1e, 0xe3, 0xb0, 0xdf, 0x82, 0x73, 0x24, 0x44, 0x20, 0x41, 0x7b, 0x0a, 0x98, + 0x1e, 0x58, 0x55, 0x9c, 0x0c, 0x38, 0x11, 0x01, 0xeb, 0xfb, 0xd6, 0x52, 0xdd, 0x68, 0x14, 0xdc, + 0x47, 0xa7, 0xb1, 0x9d, 0xf9, 0x12, 0xdb, 0x5b, 0xda, 0x83, 0xf0, 0x8f, 0x9a, 0x94, 0x39, 0x21, + 0x96, 0x41, 0x73, 0x97, 0xf4, 0xb0, 0x77, 0xdc, 0x26, 0xde, 0x34, 0xb6, 0xff, 0x9b, 0x93, 0xbf, + 0x94, 0x80, 0xa8, 0x9c, 0x04, 0xf6, 0x67, 0xd8, 0x7c, 0x09, 0xca, 0x21, 0x9e, 0x74, 0x7c, 0x32, + 0xa2, 0x58, 0x52, 0x16, 0x59, 0x59, 0xd5, 0xe3, 0xe1, 0xf5, 0x7a, 0x54, 0x74, 0x8f, 0x05, 0x05, + 0x88, 0x4a, 0x21, 0x9e, 0xb4, 0x67, 0xd0, 0x7c, 0x02, 0xd6, 0x38, 0x79, 0x33, 0xa4, 0x9c, 0xf8, + 0x1d, 0x9f, 0x44, 0x2c, 0x14, 0x56, 0xae, 0x9e, 0x6d, 0x14, 0xdc, 0xea, 0x34, 0xb6, 0x37, 0xb5, + 0xc0, 0x95, 0x04, 0x88, 0x56, 0x67, 0x91, 0xb6, 0x0a, 0x24, 0xb3, 0x10, 0x7d, 0x2c, 0x82, 0xce, + 0x2b, 0x8e, 0x3d, 0xe5, 0x73, 0xf9, 0x2f, 0x66, 0xb1, 0x28, 0x01, 0x51, 0x59, 0x05, 0x9e, 0xa6, + 0xd8, 0x6c, 0x81, 0x92, 0xce, 0x18, 0xd3, 0xc8, 0x67, 0x63, 0x2b, 0xaf, 0x8e, 0xea, 0xff, 0x69, + 0x6c, 0xff, 0x3b, 0x5f, 0xaf, 0x59, 0x88, 0x8a, 0x0a, 0x3e, 0x57, 0xc8, 0x14, 0xa0, 0x12, 0xd2, + 0xa8, 0x33, 0xc2, 0x7d, 0xea, 0x27, 0xa7, 0x39, 0xd3, 0xf8, 0x47, 0xd9, 0x74, 0xaf, 0x67, 0x73, + 0x2b, 0x1d, 0xe7, 0x6f, 0x84, 0x20, 0xda, 0x08, 0x69, 0x74, 0x90, 0x44, 0xf7, 0x08, 0x4f, 0x9b, + 0x1e, 0x82, 0x22, 0x27, 0x63, 0xcc, 0xfd, 0x4e, 0x17, 0x47, 0xbe, 0xb5, 0xa2, 0x7a, 0x3d, 0xb8, + 0x5e, 0x2f, 0x73, 0x36, 0xf9, 0xcb, 0x7a, 0x88, 0x80, 0x46, 0x2e, 0x8e, 0x7c, 0xf3, 0x05, 0x28, + 0x8c, 0x03, 0x2a, 0x49, 0x9f, 0x0a, 0x69, 0x15, 0xea, 0xd9, 0x46, 0xf1, 0x6e, 0xa5, 0xb9, 0x70, + 0x35, 0x9a, 0xea, 0x6c, 0xdc, 0x9b, 0x49, 0xbf, 0x69, 0x6c, 0xaf, 0x6b, 0xc1, 0xcb, 0x22, 0xf8, + 0xf1, 0xab, 0x5d, 0x50, 0x29, 0xbb, 0x54, 0x48, 0xf4, 0x53, 0xad, 0xb5, 0xf2, 0xfe, 0xc4, 0xce, + 0x7c, 0x3f, 0xb1, 0x0d, 0xd8, 0x02, 0xcb, 0x2a, 0xc3, 0xbc, 0x01, 0x72, 0x11, 0x0e, 0x89, 0xba, + 0x1d, 0x05, 0x77, 0x6d, 0x1a, 0xdb, 0x45, 0x2d, 0x97, 0x44, 0x21, 0x52, 0x64, 0xab, 0xf4, 0xf6, + 0xc4, 0xce, 0xa4, 0xb5, 0x19, 0xf8, 0xc9, 0x00, 0x1b, 0x3b, 0x13, 0x2f, 0xc0, 0x51, 0x8f, 0x20, + 0x2c, 0xc9, 0xfe, 0x70, 0xd0, 0x27, 0xe6, 0x2d, 0xb0, 0xac, 0x76, 0x28, 0x55, 0x5a, 0x9f, 0xc6, + 0x76, 0x49, 0x2b, 0xa9, 0x30, 0x44, 0x9a, 0x4e, 0xf6, 0x9e, 0xa4, 0xc5, 0x1d, 0x8e, 0x25, 0x49, + 0xef, 0xd6, 0x9f, 0xed, 0xfd, 0x82, 0x02, 0x44, 0x25, 0x32, 0x67, 0xe7, 0x8a, 0xdb, 0x1e, 0x28, + 0x1f, 0x30, 0x49, 0x76, 0x26, 0x92, 0x44, 0x22, 0x59, 0xb6, 0x4d, 0x90, 0x0f, 0x08, 0xed, 0x05, + 0x52, 0x39, 0xcd, 0xa2, 0x14, 0x99, 0x8f, 0x41, 0x7e, 0xc0, 0xa9, 0x47, 0x84, 0xb5, 0xa4, 0x86, + 0x5e, 0xbf, 0x32, 0xf4, 0x5f, 0x3e, 0xd9, 0xcd, 0x25, 0x9e, 0x51, 0x5a, 0xe5, 0xb6, 0x4f, 0xcf, + 0x6b, 0xc6, 0xd9, 0x79, 0xcd, 0xf8, 0x76, 0x5e, 0x33, 0xde, 0x5d, 0xd4, 0x32, 0x67, 0x17, 0xb5, + 0xcc, 0xe7, 0x8b, 0x5a, 0xe6, 0xf0, 0x76, 0x8f, 0xca, 0x60, 0xd8, 0x6d, 0x7a, 0x2c, 0x74, 0xf6, + 0x09, 0x0e, 0xef, 0x3c, 0xd3, 0x8f, 0xa0, 0xc7, 0x38, 0x71, 0x26, 0xb3, 0xb7, 0x50, 0x1e, 0x0f, + 0x88, 0xe8, 0xe6, 0xd5, 0x33, 0x76, 0xef, 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x55, 0x2e, + 0x14, 0x29, 0x05, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -460,6 +517,48 @@ func (m *ExchangeRateTuple) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *VoteExtension) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VoteExtension) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Prices) > 0 { + for iNdEx := len(m.Prices) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Prices[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Height != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintOracle(dAtA []byte, offset int, v uint64) int { offset -= sovOracle(v) base := offset @@ -536,6 +635,24 @@ func (m *ExchangeRateTuple) Size() (n int) { return n } +func (m *VoteExtension) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovOracle(uint64(m.Height)) + } + if len(m.Prices) > 0 { + for _, e := range m.Prices { + l = e.Size() + n += 1 + l + sovOracle(uint64(l)) + } + } + return n +} + func sovOracle(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -1064,6 +1181,109 @@ func (m *ExchangeRateTuple) Unmarshal(dAtA []byte) error { } return nil } +func (m *VoteExtension) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VoteExtension: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteExtension: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Prices", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Prices = append(m.Prices, ExchangeRateTuple{}) + if err := m.Prices[len(m.Prices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipOracle(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 From 2491f00174246206068f0f368df231e76c9cbd6c Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 3 May 2024 09:58:04 +0800 Subject: [PATCH 2/5] historical prices query implementation --- proto/kujira/oracle/genesis.proto | 3 +- proto/kujira/oracle/oracle.proto | 21 + proto/kujira/oracle/query.proto | 15 +- x/oracle/client/cli/query.go | 45 ++ x/oracle/genesis.go | 17 +- x/oracle/keeper/abci.go | 26 +- x/oracle/keeper/historical_rates.go | 86 ++++ x/oracle/keeper/querier.go | 17 + x/oracle/simulation/genesis.go | 1 + x/oracle/types/errors.go | 31 +- x/oracle/types/genesis.go | 15 +- x/oracle/types/genesis.pb.go | 122 +++-- x/oracle/types/keys.go | 9 + x/oracle/types/oracle.pb.go | 745 ++++++++++++++++++++++++++-- x/oracle/types/query.pb.go | 538 ++++++++++++++++++-- x/oracle/types/query.pb.gw.go | 80 +++ 16 files changed, 1623 insertions(+), 148 deletions(-) create mode 100644 x/oracle/keeper/historical_rates.go diff --git a/proto/kujira/oracle/genesis.proto b/proto/kujira/oracle/genesis.proto index 4687551f..c7a8c81c 100644 --- a/proto/kujira/oracle/genesis.proto +++ b/proto/kujira/oracle/genesis.proto @@ -12,7 +12,8 @@ message GenesisState { Params params = 1 [(gogoproto.nullable) = false]; repeated ExchangeRateTuple exchange_rates = 2 [(gogoproto.castrepeated) = "ExchangeRateTuples", (gogoproto.nullable) = false]; - repeated MissCounter miss_counters = 3 [(gogoproto.nullable) = false]; + repeated MissCounter miss_counters = 3 [(gogoproto.nullable) = false]; + repeated HistoricalExchangeRate historical_exchange_rates = 4 [(gogoproto.nullable) = false]; } // FeederDelegation is the address for where oracle feeder authority are diff --git a/proto/kujira/oracle/oracle.proto b/proto/kujira/oracle/oracle.proto index 433339d9..dfd328ea 100644 --- a/proto/kujira/oracle/oracle.proto +++ b/proto/kujira/oracle/oracle.proto @@ -47,6 +47,8 @@ message Params { (gogoproto.castrepeated) = "DenomList", (gogoproto.nullable) = false ]; + repeated PriceIntervalParam exchange_rate_snap_epochs = 10 + [ (gogoproto.nullable) = false ]; } // Denom - the object to hold configurations of each denom @@ -78,3 +80,22 @@ message VoteExtension { (gogoproto.nullable) = false ]; } + +message PriceIntervalParam { + option (gogoproto.equal) = true; + + string epoch = 1; // e.g. day + int64 duration = 2; // e.g. 86400 + int64 max_count = 3; // e.g. 30 +} + +message HistoricalExchangeRate { + string epoch = 1; + int64 timestamp = 2; + string denom = 3 [ (gogoproto.moretags) = "yaml:\"denom\"" ]; + string exchange_rate = 4 [ + (gogoproto.moretags) = "yaml:\"exchange_rate\"", + (gogoproto.customtype) = "cosmossdk.io/math.LegacyDec", + (gogoproto.nullable) = false + ]; +} diff --git a/proto/kujira/oracle/query.proto b/proto/kujira/oracle/query.proto index 46f7e571..9064f6cb 100644 --- a/proto/kujira/oracle/query.proto +++ b/proto/kujira/oracle/query.proto @@ -34,6 +34,10 @@ service Query { rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { option (google.api.http).get = "/oracle/params"; } + + rpc HistoricalExchangeRates(QueryHistoricalExchangeRatesRequest) returns (QueryHistoricalExchangeRatesResponse) { + option (google.api.http).get = "/oracle/historical_exchange_rates"; + } } // QueryExchangeRateRequest is the request type for the Query/ExchangeRate RPC method. @@ -109,4 +113,13 @@ message QueryParamsRequest {} message QueryParamsResponse { // params defines the parameters of the module. Params params = 1 [(gogoproto.nullable) = false]; -} \ No newline at end of file +} + +message QueryHistoricalExchangeRatesRequest { + string epoch = 1; + string denom = 2; +} + +message QueryHistoricalExchangeRatesResponse { + repeated HistoricalExchangeRate historical_rates = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/x/oracle/client/cli/query.go b/x/oracle/client/cli/query.go index 4009b61b..1501ffd9 100644 --- a/x/oracle/client/cli/query.go +++ b/x/oracle/client/cli/query.go @@ -82,6 +82,51 @@ $ kujirad query oracle exchange-rates KUJI return cmd } +func GetCmdQueryHistoricalExchangeRates() *cobra.Command { + cmd := &cobra.Command{ + Use: "historical-exchange-rates [epoch] [denom]", + Args: cobra.ExactArgs(2), + Short: "Query the historical exchange rates of an asset by epoch", + Long: strings.TrimSpace(` +Query the historical exchange rates of an asset by epoch. + +$ kujirad query oracle exchange-rates day KUJI +`), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + + if len(args) == 0 { + res, err := queryClient.ExchangeRates(context.Background(), &types.QueryExchangeRatesRequest{}) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + } + + res, err := queryClient.HistoricalExchangeRates( + context.Background(), + &types.QueryHistoricalExchangeRatesRequest{ + Epoch: args[0], + Denom: args[1], + }, + ) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} + // GetCmdQueryActives implements the query actives command. func GetCmdQueryActives() *cobra.Command { cmd := &cobra.Command{ diff --git a/x/oracle/genesis.go b/x/oracle/genesis.go index 6b726664..1682ea1a 100644 --- a/x/oracle/genesis.go +++ b/x/oracle/genesis.go @@ -26,6 +26,10 @@ func InitGenesis(ctx sdk.Context, keeper keeper.Keeper, data *types.GenesisState keeper.SetMissCounter(ctx, operator, mc.MissCounter) } + for _, r := range data.HistoricalExchangeRates { + keeper.SetHistoricalExchangeRate(ctx, r) + } + err := keeper.SetParams(ctx, data.Params) if err != nil { panic(err) @@ -50,6 +54,12 @@ func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { return false }) + historicalRates := []types.HistoricalExchangeRate{} + keeper.IterateHistoricalExchangeRate(ctx, func(rate types.HistoricalExchangeRate) (stop bool) { + historicalRates = append(historicalRates, rate) + return false + }) + missCounters := []types.MissCounter{} keeper.IterateMissCounters(ctx, func(operator sdk.ValAddress, missCounter uint64) (stop bool) { missCounters = append(missCounters, types.MissCounter{ @@ -59,7 +69,10 @@ func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState { return false }) - return types.NewGenesisState(params, + return types.NewGenesisState( + params, exchangeRates, - missCounters) + missCounters, + historicalRates, + ) } diff --git a/x/oracle/keeper/abci.go b/x/oracle/keeper/abci.go index 5e327695..f5225e89 100644 --- a/x/oracle/keeper/abci.go +++ b/x/oracle/keeper/abci.go @@ -10,8 +10,32 @@ import ( ) // EndBlocker is called at the end of every block -func (k Keeper) EndBlocker(_ sdk.Context) error { +func (k Keeper) EndBlocker(ctx sdk.Context) error { defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) + // Set exchange rate snapshots + params := k.GetParams(ctx) + for _, epoch := range params.ExchangeRateSnapEpochs { + for _, denom := range params.RequiredDenoms { + latestRate := k.LatestHistoricalExchangeRateByEpochDenom(ctx, epoch.Epoch, denom) + if latestRate.Timestamp == 0 || latestRate.Timestamp+epoch.Duration < ctx.BlockTime().Unix() { + rate, err := k.GetExchangeRate(ctx, denom) + if err == nil { + latestRate = types.HistoricalExchangeRate{ + Epoch: epoch.Epoch, + Timestamp: ctx.BlockTime().Unix(), + Denom: denom, + ExchangeRate: rate, + } + k.SetHistoricalExchangeRate(ctx, latestRate) + } + } + + oldestRate := k.OldestHistoricalExchangeRateByEpochDenom(ctx, epoch.Epoch, denom) + if oldestRate.Timestamp != 0 && ctx.BlockTime().Unix() > oldestRate.Timestamp+epoch.Duration*epoch.MaxCount { + k.DeleteHistoricalExchangeRate(ctx, oldestRate) + } + } + } return nil } diff --git a/x/oracle/keeper/historical_rates.go b/x/oracle/keeper/historical_rates.go new file mode 100644 index 00000000..5c7b0b29 --- /dev/null +++ b/x/oracle/keeper/historical_rates.go @@ -0,0 +1,86 @@ +package keeper + +import ( + "cosmossdk.io/errors" + storetypes "cosmossdk.io/store/types" + "github.com/Team-Kujira/core/x/oracle/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// GetExchangeRate gets the consensus exchange rate of the denom asset from the store. +func (k Keeper) GetHistoricalExchangeRate(ctx sdk.Context, epoch, denom string, timestamp int64) (types.HistoricalExchangeRate, error) { + store := ctx.KVStore(k.storeKey) + b := store.Get(types.GetHistoricalExchangeRateKey(epoch, denom, timestamp)) + if b == nil { + return types.HistoricalExchangeRate{}, errors.Wrap(types.ErrUnknownHistoricalExchangeRate, denom) + } + + ph := types.HistoricalExchangeRate{} + k.cdc.MustUnmarshal(b, &ph) + return ph, nil +} + +// SetExchangeRate sets the consensus exchange rate of the denom asset to the store. +func (k Keeper) SetHistoricalExchangeRate(ctx sdk.Context, history types.HistoricalExchangeRate) { + store := ctx.KVStore(k.storeKey) + bz := k.cdc.MustMarshal(&history) + store.Set(types.GetHistoricalExchangeRateKey(history.Epoch, history.Denom, history.Timestamp), bz) +} + +// DeleteExchangeRate deletes the consensus exchange rate of the denom asset from the store. +func (k Keeper) DeleteHistoricalExchangeRate(ctx sdk.Context, history types.HistoricalExchangeRate) { + store := ctx.KVStore(k.storeKey) + store.Delete(types.GetHistoricalExchangeRateKey(history.Epoch, history.Denom, history.Timestamp)) +} + +// IterateHistoricalExchangeRate iterates over historical exchange rates in the store +func (k Keeper) IterateHistoricalExchangeRate(ctx sdk.Context, handler func(history types.HistoricalExchangeRate) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := storetypes.KVStorePrefixIterator(store, types.HistoricalExchangeRateKey) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + ph := types.HistoricalExchangeRate{} + k.cdc.MustUnmarshal(iter.Value(), &ph) + if handler(ph) { + break + } + } +} + +// IterateHistoricalExchangeRateByEpochDenom iterates over historical exchange rates by epoch and denom in the store +func (k Keeper) IterateHistoricalExchangeRateByEpochDenom(ctx sdk.Context, epoch, denom string, handler func(history types.HistoricalExchangeRate) (stop bool)) { + store := ctx.KVStore(k.storeKey) + iter := storetypes.KVStorePrefixIterator(store, types.GetHistoricalExchangeRatePrefix(epoch, denom)) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + historicalRate := types.HistoricalExchangeRate{} + k.cdc.MustUnmarshal(iter.Value(), &historicalRate) + if handler(historicalRate) { + break + } + } +} + +func (k Keeper) LatestHistoricalExchangeRateByEpochDenom(ctx sdk.Context, epoch, denom string) types.HistoricalExchangeRate { + store := ctx.KVStore(k.storeKey) + iter := storetypes.KVStoreReversePrefixIterator(store, types.GetHistoricalExchangeRatePrefix(epoch, denom)) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + historicalRate := types.HistoricalExchangeRate{} + k.cdc.MustUnmarshal(iter.Value(), &historicalRate) + return historicalRate + } + return types.HistoricalExchangeRate{} +} + +func (k Keeper) OldestHistoricalExchangeRateByEpochDenom(ctx sdk.Context, epoch, denom string) types.HistoricalExchangeRate { + store := ctx.KVStore(k.storeKey) + iter := storetypes.KVStorePrefixIterator(store, types.GetHistoricalExchangeRatePrefix(epoch, denom)) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + historicalRate := types.HistoricalExchangeRate{} + k.cdc.MustUnmarshal(iter.Value(), &historicalRate) + return historicalRate + } + return types.HistoricalExchangeRate{} +} diff --git a/x/oracle/keeper/querier.go b/x/oracle/keeper/querier.go index 75fbb35a..ea79dd7b 100644 --- a/x/oracle/keeper/querier.go +++ b/x/oracle/keeper/querier.go @@ -94,3 +94,20 @@ func (q querier) MissCounter(c context.Context, req *types.QueryMissCounterReque MissCounter: q.GetMissCounter(ctx, valAddr), }, nil } + +// HistoricalExchangeRates queries historical exchange rates by epoch and denom +func (q querier) HistoricalExchangeRates(c context.Context, req *types.QueryHistoricalExchangeRatesRequest) (*types.QueryHistoricalExchangeRatesResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := sdk.UnwrapSDKContext(c) + historicalRates := []types.HistoricalExchangeRate{} + q.Keeper.IterateHistoricalExchangeRateByEpochDenom(ctx, req.Epoch, req.Denom, func(rate types.HistoricalExchangeRate) (stop bool) { + historicalRates = append(historicalRates, rate) + return false + }) + return &types.QueryHistoricalExchangeRatesResponse{ + HistoricalRates: historicalRates, + }, nil +} diff --git a/x/oracle/simulation/genesis.go b/x/oracle/simulation/genesis.go index 0c97222d..3435b54d 100644 --- a/x/oracle/simulation/genesis.go +++ b/x/oracle/simulation/genesis.go @@ -109,6 +109,7 @@ func RandomizedGenState(simState *module.SimulationState) { }, []types.ExchangeRateTuple{}, []types.MissCounter{}, + []types.HistoricalExchangeRate{}, ) bz, err := json.MarshalIndent(&oracleGenesis.Params, "", " ") diff --git a/x/oracle/types/errors.go b/x/oracle/types/errors.go index 4358b76f..831edca8 100644 --- a/x/oracle/types/errors.go +++ b/x/oracle/types/errors.go @@ -10,19 +10,20 @@ import ( // Oracle Errors var ( - ErrInvalidExchangeRate = errors.Register(ModuleName, 1, "invalid exchange rate") - ErrNoPrevote = errors.Register(ModuleName, 2, "no prevote") - ErrNoVote = errors.Register(ModuleName, 3, "no vote") - ErrNoVotingPermission = errors.Register(ModuleName, 4, "unauthorized voter") - ErrInvalidHash = errors.Register(ModuleName, 5, "invalid hash") - ErrInvalidHashLength = errors.Register(ModuleName, 6, fmt.Sprintf("invalid hash length; should equal %d", tmhash.TruncatedSize)) - ErrVerificationFailed = errors.Register(ModuleName, 7, "hash verification failed") - ErrRevealPeriodMissMatch = errors.Register(ModuleName, 8, "reveal period of submitted vote do not match with registered prevote") - ErrInvalidSaltLength = errors.Register(ModuleName, 9, "invalid salt length; must be 64") - ErrInvalidSaltFormat = errors.Register(ModuleName, 10, "invalid salt format") - ErrNoAggregatePrevote = errors.Register(ModuleName, 11, "no aggregate prevote") - ErrNoAggregateVote = errors.Register(ModuleName, 12, "no aggregate vote") - ErrUnknownDenom = errors.Register(ModuleName, 13, "unknown denom") - ErrBallotNotSorted = errors.Register(ModuleName, 14, "ballot not sorted") - ErrSetParams = errors.Register(ModuleName, 15, "could not set params") + ErrInvalidExchangeRate = errors.Register(ModuleName, 1, "invalid exchange rate") + ErrNoPrevote = errors.Register(ModuleName, 2, "no prevote") + ErrNoVote = errors.Register(ModuleName, 3, "no vote") + ErrNoVotingPermission = errors.Register(ModuleName, 4, "unauthorized voter") + ErrInvalidHash = errors.Register(ModuleName, 5, "invalid hash") + ErrInvalidHashLength = errors.Register(ModuleName, 6, fmt.Sprintf("invalid hash length; should equal %d", tmhash.TruncatedSize)) + ErrVerificationFailed = errors.Register(ModuleName, 7, "hash verification failed") + ErrRevealPeriodMissMatch = errors.Register(ModuleName, 8, "reveal period of submitted vote do not match with registered prevote") + ErrInvalidSaltLength = errors.Register(ModuleName, 9, "invalid salt length; must be 64") + ErrInvalidSaltFormat = errors.Register(ModuleName, 10, "invalid salt format") + ErrNoAggregatePrevote = errors.Register(ModuleName, 11, "no aggregate prevote") + ErrNoAggregateVote = errors.Register(ModuleName, 12, "no aggregate vote") + ErrUnknownDenom = errors.Register(ModuleName, 13, "unknown denom") + ErrBallotNotSorted = errors.Register(ModuleName, 14, "ballot not sorted") + ErrSetParams = errors.Register(ModuleName, 15, "could not set params") + ErrUnknownHistoricalExchangeRate = errors.Register(ModuleName, 16, "unknown historical exchange rate") ) diff --git a/x/oracle/types/genesis.go b/x/oracle/types/genesis.go index d78500e3..709555db 100644 --- a/x/oracle/types/genesis.go +++ b/x/oracle/types/genesis.go @@ -8,19 +8,24 @@ import ( func NewGenesisState( params Params, rates []ExchangeRateTuple, missCounters []MissCounter, + historicalRates []HistoricalExchangeRate, ) *GenesisState { return &GenesisState{ - Params: params, - ExchangeRates: rates, - MissCounters: missCounters, + Params: params, + ExchangeRates: rates, + MissCounters: missCounters, + HistoricalExchangeRates: historicalRates, } } // DefaultGenesisState - default GenesisState used by columbus-2 func DefaultGenesisState() *GenesisState { - return NewGenesisState(DefaultParams(), + return NewGenesisState( + DefaultParams(), []ExchangeRateTuple{}, - []MissCounter{}) + []MissCounter{}, + []HistoricalExchangeRate{}, + ) } // ValidateGenesis validates the oracle genesis state diff --git a/x/oracle/types/genesis.pb.go b/x/oracle/types/genesis.pb.go index 0057a812..9e9a56d6 100644 --- a/x/oracle/types/genesis.pb.go +++ b/x/oracle/types/genesis.pb.go @@ -26,9 +26,10 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // GenesisState defines the oracle module's genesis state. type GenesisState struct { - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` - ExchangeRates ExchangeRateTuples `protobuf:"bytes,2,rep,name=exchange_rates,json=exchangeRates,proto3,castrepeated=ExchangeRateTuples" json:"exchange_rates"` - MissCounters []MissCounter `protobuf:"bytes,3,rep,name=miss_counters,json=missCounters,proto3" json:"miss_counters"` + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + ExchangeRates ExchangeRateTuples `protobuf:"bytes,2,rep,name=exchange_rates,json=exchangeRates,proto3,castrepeated=ExchangeRateTuples" json:"exchange_rates"` + MissCounters []MissCounter `protobuf:"bytes,3,rep,name=miss_counters,json=missCounters,proto3" json:"miss_counters"` + HistoricalExchangeRates []HistoricalExchangeRate `protobuf:"bytes,4,rep,name=historical_exchange_rates,json=historicalExchangeRates,proto3" json:"historical_exchange_rates"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -85,6 +86,13 @@ func (m *GenesisState) GetMissCounters() []MissCounter { return nil } +func (m *GenesisState) GetHistoricalExchangeRates() []HistoricalExchangeRate { + if m != nil { + return m.HistoricalExchangeRates + } + return nil +} + // FeederDelegation is the address for where oracle feeder authority are // delegated to. By default this struct is only used at genesis to feed in // default feeder addresses. @@ -203,32 +211,34 @@ func init() { func init() { proto.RegisterFile("kujira/oracle/genesis.proto", fileDescriptor_fb93724cfbd1d6a0) } var fileDescriptor_fb93724cfbd1d6a0 = []byte{ - // 396 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xd1, 0x8a, 0xd3, 0x40, - 0x14, 0x86, 0x93, 0xdd, 0x65, 0xc1, 0x49, 0xb3, 0xac, 0x83, 0x42, 0x89, 0x90, 0xad, 0x05, 0x61, - 0x51, 0xcc, 0xb0, 0xbb, 0x4f, 0x60, 0xdd, 0xd5, 0x0b, 0x11, 0x24, 0xee, 0x95, 0x20, 0x65, 0x32, - 0x39, 0x9b, 0x8e, 0x26, 0x99, 0x30, 0x67, 0x52, 0xea, 0x5b, 0xf8, 0x1c, 0x3e, 0x49, 0x2f, 0x7b, - 0xe9, 0x95, 0x4a, 0xfb, 0x00, 0xbe, 0x82, 0x34, 0x13, 0x6d, 0x5a, 0x7b, 0x35, 0xc3, 0xff, 0xfd, - 0xe7, 0xfc, 0xe7, 0xc0, 0x21, 0x8f, 0x3e, 0xd7, 0x9f, 0xa4, 0xe6, 0x4c, 0x69, 0x2e, 0x72, 0x60, - 0x19, 0x94, 0x80, 0x12, 0xa3, 0x4a, 0x2b, 0xa3, 0xa8, 0x6f, 0x61, 0x64, 0x61, 0xf0, 0x20, 0x53, - 0x99, 0x6a, 0x08, 0x5b, 0xff, 0xac, 0x29, 0x08, 0xb6, 0x3b, 0xd8, 0xa7, 0x65, 0xa1, 0x50, 0x58, - 0x28, 0x64, 0x09, 0x47, 0x60, 0xd3, 0x8b, 0x04, 0x0c, 0xbf, 0x60, 0x42, 0xc9, 0xd2, 0xf2, 0xe1, - 0x6f, 0x97, 0xf4, 0x5e, 0xdb, 0xc8, 0xf7, 0x86, 0x1b, 0xa0, 0x57, 0xe4, 0xb8, 0xe2, 0x9a, 0x17, - 0xd8, 0x77, 0x07, 0xee, 0xb9, 0x77, 0xf9, 0x30, 0xda, 0x1a, 0x21, 0x7a, 0xd7, 0xc0, 0xd1, 0xd1, - 0xfc, 0xc7, 0x99, 0x13, 0xb7, 0x56, 0x2a, 0xc8, 0x09, 0xcc, 0xc4, 0x84, 0x97, 0x19, 0x8c, 0x35, - 0x37, 0x80, 0xfd, 0x83, 0xc1, 0xe1, 0xb9, 0x77, 0x39, 0xd8, 0x29, 0xbe, 0x69, 0x4d, 0x31, 0x37, - 0x70, 0x5b, 0x57, 0x39, 0x8c, 0x82, 0x75, 0x9f, 0x6f, 0x3f, 0xcf, 0xe8, 0x7f, 0x08, 0x63, 0x1f, - 0x3a, 0x1a, 0xd2, 0x1b, 0xe2, 0x17, 0x12, 0x71, 0x2c, 0x54, 0x5d, 0x1a, 0xd0, 0xd8, 0x3f, 0x6c, - 0x32, 0x82, 0x9d, 0x8c, 0xb7, 0x12, 0xf1, 0xa5, 0xb5, 0xb4, 0x53, 0xf6, 0x8a, 0x8d, 0x84, 0xc3, - 0x3b, 0x72, 0xfa, 0x0a, 0x20, 0x05, 0x7d, 0x0d, 0x39, 0x64, 0xdc, 0x48, 0x55, 0xd2, 0x27, 0xe4, - 0xe4, 0xae, 0xd1, 0xc6, 0x3c, 0x4d, 0x35, 0xa0, 0x5d, 0xfe, 0x5e, 0xec, 0x5b, 0xf5, 0x85, 0x15, - 0xe9, 0x33, 0x72, 0x7f, 0xca, 0x73, 0x99, 0x72, 0xa3, 0x36, 0xce, 0x83, 0xc6, 0x79, 0xfa, 0x0f, - 0xb4, 0xe6, 0xe1, 0x47, 0xe2, 0x75, 0x46, 0xd9, 0x5f, 0xeb, 0xee, 0xaf, 0xa5, 0x8f, 0x49, 0xaf, - 0xbb, 0x6a, 0x93, 0x71, 0x14, 0x7b, 0x9d, 0x3d, 0x46, 0xd7, 0xf3, 0x65, 0xe8, 0x2e, 0x96, 0xa1, - 0xfb, 0x6b, 0x19, 0xba, 0x5f, 0x57, 0xa1, 0xb3, 0x58, 0x85, 0xce, 0xf7, 0x55, 0xe8, 0x7c, 0x78, - 0x9a, 0x49, 0x33, 0xa9, 0x93, 0x48, 0xa8, 0x82, 0xdd, 0x02, 0x2f, 0x9e, 0xbf, 0xb1, 0xe7, 0x21, - 0x94, 0x06, 0x36, 0xfb, 0x7b, 0x25, 0xe6, 0x4b, 0x05, 0x98, 0x1c, 0x37, 0x57, 0x70, 0xf5, 0x27, - 0x00, 0x00, 0xff, 0xff, 0x7b, 0x19, 0x13, 0x2d, 0x85, 0x02, 0x00, 0x00, + // 426 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x92, 0xd1, 0x6a, 0x13, 0x41, + 0x14, 0x86, 0xb3, 0x69, 0x28, 0x38, 0x49, 0x4a, 0x1d, 0x14, 0xe3, 0x0a, 0xdb, 0x18, 0x28, 0x14, + 0xc5, 0x1d, 0xda, 0x3e, 0x81, 0xb1, 0x55, 0x41, 0x04, 0x59, 0x7b, 0x25, 0x48, 0x38, 0x99, 0x9c, + 0x6e, 0x46, 0x77, 0x77, 0xc2, 0x9c, 0xd9, 0x52, 0xdf, 0xc2, 0xe7, 0xf0, 0x49, 0x7a, 0xd9, 0xcb, + 0x5e, 0xa9, 0x24, 0x2f, 0x22, 0x9d, 0x59, 0xdb, 0xed, 0x36, 0x57, 0xbb, 0xfc, 0xdf, 0x7f, 0xfe, + 0x73, 0xe6, 0x70, 0xd8, 0xb3, 0xef, 0xe5, 0x37, 0x65, 0x40, 0x68, 0x03, 0x32, 0x43, 0x91, 0x62, + 0x81, 0xa4, 0x28, 0x5e, 0x18, 0x6d, 0x35, 0xef, 0x7b, 0x18, 0x7b, 0x18, 0x3e, 0x4a, 0x75, 0xaa, + 0x1d, 0x11, 0xd7, 0x7f, 0xde, 0x14, 0x86, 0x77, 0x13, 0xfc, 0xa7, 0x62, 0x91, 0xd4, 0x94, 0x6b, + 0x12, 0x53, 0x20, 0x14, 0x67, 0xfb, 0x53, 0xb4, 0xb0, 0x2f, 0xa4, 0x56, 0x85, 0xe7, 0xa3, 0xab, + 0x36, 0xeb, 0xbd, 0xf3, 0x2d, 0x3f, 0x5b, 0xb0, 0xc8, 0x0f, 0xd9, 0xe6, 0x02, 0x0c, 0xe4, 0x34, + 0x08, 0x86, 0xc1, 0x5e, 0xf7, 0xe0, 0x71, 0x7c, 0x67, 0x84, 0xf8, 0x93, 0x83, 0xe3, 0xce, 0xc5, + 0xef, 0x9d, 0x56, 0x52, 0x59, 0xb9, 0x64, 0x5b, 0x78, 0x2e, 0xe7, 0x50, 0xa4, 0x38, 0x31, 0x60, + 0x91, 0x06, 0xed, 0xe1, 0xc6, 0x5e, 0xf7, 0x60, 0xd8, 0x28, 0x3e, 0xae, 0x4c, 0x09, 0x58, 0x3c, + 0x29, 0x17, 0x19, 0x8e, 0xc3, 0xeb, 0x9c, 0x5f, 0x7f, 0x76, 0xf8, 0x3d, 0x44, 0x49, 0x1f, 0x6b, + 0x1a, 0xf1, 0x63, 0xd6, 0xcf, 0x15, 0xd1, 0x44, 0xea, 0xb2, 0xb0, 0x68, 0x68, 0xb0, 0xe1, 0x7a, + 0x84, 0x8d, 0x1e, 0x1f, 0x15, 0xd1, 0x1b, 0x6f, 0xa9, 0xa6, 0xec, 0xe5, 0xb7, 0x12, 0xf1, 0x94, + 0x3d, 0x9d, 0x2b, 0xb2, 0xda, 0x28, 0x09, 0xd9, 0xa4, 0x31, 0x76, 0xc7, 0x45, 0xee, 0x36, 0x22, + 0xdf, 0xdf, 0xf8, 0xeb, 0x53, 0x56, 0xe9, 0x4f, 0xe6, 0x6b, 0x29, 0x8d, 0x4e, 0xd9, 0xf6, 0x5b, + 0xc4, 0x19, 0x9a, 0x23, 0xcc, 0x30, 0x05, 0xab, 0x74, 0xc1, 0x77, 0xd9, 0xd6, 0xa9, 0xd3, 0x26, + 0x30, 0x9b, 0x19, 0x24, 0xbf, 0xe5, 0x07, 0x49, 0xdf, 0xab, 0xaf, 0xbd, 0xc8, 0x5f, 0xb2, 0x87, + 0x67, 0x90, 0xa9, 0x19, 0x58, 0x7d, 0xeb, 0x6c, 0x3b, 0xe7, 0xf6, 0x0d, 0xa8, 0xcc, 0xa3, 0xaf, + 0xac, 0x5b, 0x7b, 0xf3, 0xfa, 0xda, 0x60, 0x7d, 0x2d, 0x7f, 0xce, 0x7a, 0xf5, 0x9d, 0xba, 0x1e, + 0x9d, 0xa4, 0x5b, 0x5b, 0xd8, 0xf8, 0xe8, 0x62, 0x19, 0x05, 0x97, 0xcb, 0x28, 0xf8, 0xbb, 0x8c, + 0x82, 0x9f, 0xab, 0xa8, 0x75, 0xb9, 0x8a, 0x5a, 0x57, 0xab, 0xa8, 0xf5, 0xe5, 0x45, 0xaa, 0xec, + 0xbc, 0x9c, 0xc6, 0x52, 0xe7, 0xe2, 0x04, 0x21, 0x7f, 0xf5, 0xc1, 0xdf, 0xa1, 0xd4, 0x06, 0xc5, + 0xf9, 0xff, 0x73, 0xb4, 0x3f, 0x16, 0x48, 0xd3, 0x4d, 0x77, 0x6e, 0x87, 0xff, 0x02, 0x00, 0x00, + 0xff, 0xff, 0x7b, 0xa3, 0x6b, 0x17, 0xee, 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -251,6 +261,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.HistoricalExchangeRates) > 0 { + for iNdEx := len(m.HistoricalExchangeRates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.HistoricalExchangeRates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } if len(m.MissCounters) > 0 { for iNdEx := len(m.MissCounters) - 1; iNdEx >= 0; iNdEx-- { { @@ -395,6 +419,12 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } + if len(m.HistoricalExchangeRates) > 0 { + for _, e := range m.HistoricalExchangeRates { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } return n } @@ -567,6 +597,40 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HistoricalExchangeRates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HistoricalExchangeRates = append(m.HistoricalExchangeRates, HistoricalExchangeRate{}) + if err := m.HistoricalExchangeRates[len(m.HistoricalExchangeRates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/oracle/types/keys.go b/x/oracle/types/keys.go index b72e25ec..9aa1426e 100644 --- a/x/oracle/types/keys.go +++ b/x/oracle/types/keys.go @@ -42,8 +42,17 @@ var ( AggregateExchangeRateVoteKey = []byte{0x05} // prefix for each key to a aggregate vote ParamsKey = []byte{0x06} WhitelistKey = []byte{0x07} + HistoricalExchangeRateKey = []byte{0x08} ) +func GetHistoricalExchangeRatePrefix(epoch string, denom string) []byte { + return append(append(HistoricalExchangeRateKey, []byte(epoch)...), []byte(denom)...) +} + +func GetHistoricalExchangeRateKey(epoch string, denom string, timestamp int64) []byte { + return append(GetHistoricalExchangeRatePrefix(epoch, denom), sdk.Uint64ToBigEndian(uint64(timestamp))...) +} + // GetExchangeRateKey - stored by *denom* func GetExchangeRateKey(denom string) []byte { return append(ExchangeRateKey, []byte(denom)...) diff --git a/x/oracle/types/oracle.pb.go b/x/oracle/types/oracle.pb.go index e54a510f..45a48df7 100644 --- a/x/oracle/types/oracle.pb.go +++ b/x/oracle/types/oracle.pb.go @@ -35,8 +35,9 @@ type Params struct { SlashWindow uint64 `protobuf:"varint,6,opt,name=slash_window,json=slashWindow,proto3" json:"slash_window,omitempty" yaml:"slash_window"` MinValidPerWindow cosmossdk_io_math.LegacyDec `protobuf:"bytes,7,opt,name=min_valid_per_window,json=minValidPerWindow,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"min_valid_per_window" yaml:"min_valid_per_window"` // Deprecated - RewardBand cosmossdk_io_math.LegacyDec `protobuf:"bytes,8,opt,name=reward_band,json=rewardBand,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"reward_band" yaml:"reward_band"` - Whitelist DenomList `protobuf:"bytes,9,rep,name=whitelist,proto3,castrepeated=DenomList" json:"whitelist" yaml:"whitelist"` + RewardBand cosmossdk_io_math.LegacyDec `protobuf:"bytes,8,opt,name=reward_band,json=rewardBand,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"reward_band" yaml:"reward_band"` + Whitelist DenomList `protobuf:"bytes,9,rep,name=whitelist,proto3,castrepeated=DenomList" json:"whitelist" yaml:"whitelist"` + ExchangeRateSnapEpochs []PriceIntervalParam `protobuf:"bytes,10,rep,name=exchange_rate_snap_epochs,json=exchangeRateSnapEpochs,proto3" json:"exchange_rate_snap_epochs"` } func (m *Params) Reset() { *m = Params{} } @@ -99,6 +100,13 @@ func (m *Params) GetWhitelist() DenomList { return nil } +func (m *Params) GetExchangeRateSnapEpochs() []PriceIntervalParam { + if m != nil { + return m.ExchangeRateSnapEpochs + } + return nil +} + // Denom - the object to hold configurations of each denom type Denom struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` @@ -226,61 +234,192 @@ func (m *VoteExtension) GetPrices() []ExchangeRateTuple { return nil } +type PriceIntervalParam struct { + Epoch string `protobuf:"bytes,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Duration int64 `protobuf:"varint,2,opt,name=duration,proto3" json:"duration,omitempty"` + MaxCount int64 `protobuf:"varint,3,opt,name=max_count,json=maxCount,proto3" json:"max_count,omitempty"` +} + +func (m *PriceIntervalParam) Reset() { *m = PriceIntervalParam{} } +func (m *PriceIntervalParam) String() string { return proto.CompactTextString(m) } +func (*PriceIntervalParam) ProtoMessage() {} +func (*PriceIntervalParam) Descriptor() ([]byte, []int) { + return fileDescriptor_8fffe8fb5ee63325, []int{4} +} +func (m *PriceIntervalParam) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PriceIntervalParam) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PriceIntervalParam.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *PriceIntervalParam) XXX_Merge(src proto.Message) { + xxx_messageInfo_PriceIntervalParam.Merge(m, src) +} +func (m *PriceIntervalParam) XXX_Size() int { + return m.Size() +} +func (m *PriceIntervalParam) XXX_DiscardUnknown() { + xxx_messageInfo_PriceIntervalParam.DiscardUnknown(m) +} + +var xxx_messageInfo_PriceIntervalParam proto.InternalMessageInfo + +func (m *PriceIntervalParam) GetEpoch() string { + if m != nil { + return m.Epoch + } + return "" +} + +func (m *PriceIntervalParam) GetDuration() int64 { + if m != nil { + return m.Duration + } + return 0 +} + +func (m *PriceIntervalParam) GetMaxCount() int64 { + if m != nil { + return m.MaxCount + } + return 0 +} + +type HistoricalExchangeRate struct { + Epoch string `protobuf:"bytes,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Denom string `protobuf:"bytes,3,opt,name=denom,proto3" json:"denom,omitempty" yaml:"denom"` + ExchangeRate cosmossdk_io_math.LegacyDec `protobuf:"bytes,4,opt,name=exchange_rate,json=exchangeRate,proto3,customtype=cosmossdk.io/math.LegacyDec" json:"exchange_rate" yaml:"exchange_rate"` +} + +func (m *HistoricalExchangeRate) Reset() { *m = HistoricalExchangeRate{} } +func (m *HistoricalExchangeRate) String() string { return proto.CompactTextString(m) } +func (*HistoricalExchangeRate) ProtoMessage() {} +func (*HistoricalExchangeRate) Descriptor() ([]byte, []int) { + return fileDescriptor_8fffe8fb5ee63325, []int{5} +} +func (m *HistoricalExchangeRate) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *HistoricalExchangeRate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_HistoricalExchangeRate.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *HistoricalExchangeRate) XXX_Merge(src proto.Message) { + xxx_messageInfo_HistoricalExchangeRate.Merge(m, src) +} +func (m *HistoricalExchangeRate) XXX_Size() int { + return m.Size() +} +func (m *HistoricalExchangeRate) XXX_DiscardUnknown() { + xxx_messageInfo_HistoricalExchangeRate.DiscardUnknown(m) +} + +var xxx_messageInfo_HistoricalExchangeRate proto.InternalMessageInfo + +func (m *HistoricalExchangeRate) GetEpoch() string { + if m != nil { + return m.Epoch + } + return "" +} + +func (m *HistoricalExchangeRate) GetTimestamp() int64 { + if m != nil { + return m.Timestamp + } + return 0 +} + +func (m *HistoricalExchangeRate) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + func init() { proto.RegisterType((*Params)(nil), "kujira.oracle.Params") proto.RegisterType((*Denom)(nil), "kujira.oracle.Denom") proto.RegisterType((*ExchangeRateTuple)(nil), "kujira.oracle.ExchangeRateTuple") proto.RegisterType((*VoteExtension)(nil), "kujira.oracle.VoteExtension") + proto.RegisterType((*PriceIntervalParam)(nil), "kujira.oracle.PriceIntervalParam") + proto.RegisterType((*HistoricalExchangeRate)(nil), "kujira.oracle.HistoricalExchangeRate") } func init() { proto.RegisterFile("kujira/oracle/oracle.proto", fileDescriptor_8fffe8fb5ee63325) } var fileDescriptor_8fffe8fb5ee63325 = []byte{ - // 693 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x3d, 0x6f, 0x13, 0x4b, - 0x14, 0xf5, 0xc6, 0x8e, 0x5f, 0x3c, 0xb6, 0xf3, 0xb1, 0xcf, 0x2f, 0x6f, 0xe5, 0x48, 0x5e, 0x6b, - 0x10, 0xc8, 0x42, 0xc2, 0xab, 0x40, 0x81, 0x30, 0x88, 0x62, 0x71, 0x68, 0x48, 0x11, 0x8d, 0xa2, - 0x20, 0xd2, 0x98, 0xf1, 0xee, 0xe0, 0x1d, 0xe2, 0xdd, 0x31, 0x33, 0xe3, 0x8f, 0xfc, 0x03, 0x4a, - 0x4a, 0xca, 0x14, 0x54, 0xf0, 0x47, 0x52, 0xa6, 0x44, 0x14, 0x0b, 0x4a, 0x1a, 0x6a, 0xff, 0x02, - 0xb4, 0x33, 0xeb, 0x60, 0x07, 0x8a, 0x40, 0x65, 0x9f, 0x7b, 0xee, 0x3d, 0xf7, 0xec, 0x9d, 0x3b, - 0x03, 0xaa, 0x47, 0xc3, 0xd7, 0x94, 0x63, 0x87, 0x71, 0xec, 0xf5, 0x49, 0xfa, 0xd3, 0x1c, 0x70, - 0x26, 0x99, 0x59, 0xd6, 0x5c, 0x53, 0x07, 0xab, 0x95, 0x1e, 0xeb, 0x31, 0xc5, 0x38, 0xc9, 0x3f, - 0x9d, 0x54, 0xad, 0x79, 0x4c, 0x84, 0x4c, 0x38, 0x5d, 0x2c, 0x88, 0x33, 0xda, 0xee, 0x12, 0x89, - 0xb7, 0x1d, 0x8f, 0xd1, 0x48, 0xf3, 0xf0, 0x43, 0x1e, 0xe4, 0xf7, 0x30, 0xc7, 0xa1, 0x30, 0xef, - 0x83, 0xe2, 0x88, 0x49, 0xd2, 0x19, 0x10, 0x4e, 0x99, 0x6f, 0x19, 0x75, 0xa3, 0x91, 0x73, 0x37, - 0xa7, 0xb1, 0x6d, 0x1e, 0xe3, 0xb0, 0xdf, 0x82, 0x73, 0x24, 0x44, 0x20, 0x41, 0x7b, 0x0a, 0x98, - 0x1e, 0x58, 0x55, 0x9c, 0x0c, 0x38, 0x11, 0x01, 0xeb, 0xfb, 0xd6, 0x52, 0xdd, 0x68, 0x14, 0xdc, - 0x47, 0xa7, 0xb1, 0x9d, 0xf9, 0x12, 0xdb, 0x5b, 0xda, 0x83, 0xf0, 0x8f, 0x9a, 0x94, 0x39, 0x21, - 0x96, 0x41, 0x73, 0x97, 0xf4, 0xb0, 0x77, 0xdc, 0x26, 0xde, 0x34, 0xb6, 0xff, 0x9b, 0x93, 0xbf, - 0x94, 0x80, 0xa8, 0x9c, 0x04, 0xf6, 0x67, 0xd8, 0x7c, 0x09, 0xca, 0x21, 0x9e, 0x74, 0x7c, 0x32, - 0xa2, 0x58, 0x52, 0x16, 0x59, 0x59, 0xd5, 0xe3, 0xe1, 0xf5, 0x7a, 0x54, 0x74, 0x8f, 0x05, 0x05, - 0x88, 0x4a, 0x21, 0x9e, 0xb4, 0x67, 0xd0, 0x7c, 0x02, 0xd6, 0x38, 0x79, 0x33, 0xa4, 0x9c, 0xf8, - 0x1d, 0x9f, 0x44, 0x2c, 0x14, 0x56, 0xae, 0x9e, 0x6d, 0x14, 0xdc, 0xea, 0x34, 0xb6, 0x37, 0xb5, - 0xc0, 0x95, 0x04, 0x88, 0x56, 0x67, 0x91, 0xb6, 0x0a, 0x24, 0xb3, 0x10, 0x7d, 0x2c, 0x82, 0xce, - 0x2b, 0x8e, 0x3d, 0xe5, 0x73, 0xf9, 0x2f, 0x66, 0xb1, 0x28, 0x01, 0x51, 0x59, 0x05, 0x9e, 0xa6, - 0xd8, 0x6c, 0x81, 0x92, 0xce, 0x18, 0xd3, 0xc8, 0x67, 0x63, 0x2b, 0xaf, 0x8e, 0xea, 0xff, 0x69, - 0x6c, 0xff, 0x3b, 0x5f, 0xaf, 0x59, 0x88, 0x8a, 0x0a, 0x3e, 0x57, 0xc8, 0x14, 0xa0, 0x12, 0xd2, - 0xa8, 0x33, 0xc2, 0x7d, 0xea, 0x27, 0xa7, 0x39, 0xd3, 0xf8, 0x47, 0xd9, 0x74, 0xaf, 0x67, 0x73, - 0x2b, 0x1d, 0xe7, 0x6f, 0x84, 0x20, 0xda, 0x08, 0x69, 0x74, 0x90, 0x44, 0xf7, 0x08, 0x4f, 0x9b, - 0x1e, 0x82, 0x22, 0x27, 0x63, 0xcc, 0xfd, 0x4e, 0x17, 0x47, 0xbe, 0xb5, 0xa2, 0x7a, 0x3d, 0xb8, - 0x5e, 0x2f, 0x73, 0x36, 0xf9, 0xcb, 0x7a, 0x88, 0x80, 0x46, 0x2e, 0x8e, 0x7c, 0xf3, 0x05, 0x28, - 0x8c, 0x03, 0x2a, 0x49, 0x9f, 0x0a, 0x69, 0x15, 0xea, 0xd9, 0x46, 0xf1, 0x6e, 0xa5, 0xb9, 0x70, - 0x35, 0x9a, 0xea, 0x6c, 0xdc, 0x9b, 0x49, 0xbf, 0x69, 0x6c, 0xaf, 0x6b, 0xc1, 0xcb, 0x22, 0xf8, - 0xf1, 0xab, 0x5d, 0x50, 0x29, 0xbb, 0x54, 0x48, 0xf4, 0x53, 0xad, 0xb5, 0xf2, 0xfe, 0xc4, 0xce, - 0x7c, 0x3f, 0xb1, 0x0d, 0xd8, 0x02, 0xcb, 0x2a, 0xc3, 0xbc, 0x01, 0x72, 0x11, 0x0e, 0x89, 0xba, - 0x1d, 0x05, 0x77, 0x6d, 0x1a, 0xdb, 0x45, 0x2d, 0x97, 0x44, 0x21, 0x52, 0x64, 0xab, 0xf4, 0xf6, - 0xc4, 0xce, 0xa4, 0xb5, 0x19, 0xf8, 0xc9, 0x00, 0x1b, 0x3b, 0x13, 0x2f, 0xc0, 0x51, 0x8f, 0x20, - 0x2c, 0xc9, 0xfe, 0x70, 0xd0, 0x27, 0xe6, 0x2d, 0xb0, 0xac, 0x76, 0x28, 0x55, 0x5a, 0x9f, 0xc6, - 0x76, 0x49, 0x2b, 0xa9, 0x30, 0x44, 0x9a, 0x4e, 0xf6, 0x9e, 0xa4, 0xc5, 0x1d, 0x8e, 0x25, 0x49, - 0xef, 0xd6, 0x9f, 0xed, 0xfd, 0x82, 0x02, 0x44, 0x25, 0x32, 0x67, 0xe7, 0x8a, 0xdb, 0x1e, 0x28, - 0x1f, 0x30, 0x49, 0x76, 0x26, 0x92, 0x44, 0x22, 0x59, 0xb6, 0x4d, 0x90, 0x0f, 0x08, 0xed, 0x05, - 0x52, 0x39, 0xcd, 0xa2, 0x14, 0x99, 0x8f, 0x41, 0x7e, 0xc0, 0xa9, 0x47, 0x84, 0xb5, 0xa4, 0x86, - 0x5e, 0xbf, 0x32, 0xf4, 0x5f, 0x3e, 0xd9, 0xcd, 0x25, 0x9e, 0x51, 0x5a, 0xe5, 0xb6, 0x4f, 0xcf, - 0x6b, 0xc6, 0xd9, 0x79, 0xcd, 0xf8, 0x76, 0x5e, 0x33, 0xde, 0x5d, 0xd4, 0x32, 0x67, 0x17, 0xb5, - 0xcc, 0xe7, 0x8b, 0x5a, 0xe6, 0xf0, 0x76, 0x8f, 0xca, 0x60, 0xd8, 0x6d, 0x7a, 0x2c, 0x74, 0xf6, - 0x09, 0x0e, 0xef, 0x3c, 0xd3, 0x8f, 0xa0, 0xc7, 0x38, 0x71, 0x26, 0xb3, 0xb7, 0x50, 0x1e, 0x0f, - 0x88, 0xe8, 0xe6, 0xd5, 0x33, 0x76, 0xef, 0x47, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x55, 0x2e, - 0x14, 0x29, 0x05, 0x00, 0x00, + // 828 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcf, 0x8f, 0xe3, 0x34, + 0x14, 0x6e, 0xa6, 0x9d, 0xee, 0xc4, 0x6d, 0xf7, 0x87, 0x29, 0x25, 0x74, 0x50, 0x53, 0x8c, 0x40, + 0x23, 0x24, 0x1a, 0x2d, 0x1c, 0x10, 0x05, 0x71, 0xc8, 0xce, 0x20, 0x10, 0x7b, 0x18, 0x99, 0xd1, + 0x22, 0xf6, 0x12, 0xdc, 0xc4, 0x34, 0x66, 0x93, 0x38, 0xd8, 0x6e, 0xa7, 0xf3, 0x1f, 0xec, 0x91, + 0x23, 0xc7, 0x39, 0xc3, 0x3f, 0xb2, 0xc7, 0x3d, 0x21, 0xc4, 0x21, 0xa0, 0x99, 0x0b, 0xe7, 0xfe, + 0x05, 0x28, 0x76, 0x3a, 0xd3, 0x76, 0x41, 0x9a, 0x45, 0x9c, 0xda, 0xef, 0x3d, 0xfb, 0xfb, 0x3e, + 0xbf, 0x97, 0x67, 0x83, 0xfe, 0x93, 0xd9, 0xf7, 0x4c, 0x10, 0x8f, 0x0b, 0x12, 0x26, 0xb4, 0xfa, + 0x19, 0xe5, 0x82, 0x2b, 0x0e, 0x3b, 0x26, 0x37, 0x32, 0xc1, 0x7e, 0x77, 0xca, 0xa7, 0x5c, 0x67, + 0xbc, 0xf2, 0x9f, 0x59, 0xd4, 0x1f, 0x84, 0x5c, 0xa6, 0x5c, 0x7a, 0x13, 0x22, 0xa9, 0x37, 0xbf, + 0x3f, 0xa1, 0x8a, 0xdc, 0xf7, 0x42, 0xce, 0x32, 0x93, 0x47, 0x4f, 0x6f, 0x81, 0xe6, 0x31, 0x11, + 0x24, 0x95, 0xf0, 0x43, 0xd0, 0x9a, 0x73, 0x45, 0x83, 0x9c, 0x0a, 0xc6, 0x23, 0xc7, 0x1a, 0x5a, + 0x07, 0x0d, 0xbf, 0xb7, 0x2c, 0x5c, 0x78, 0x46, 0xd2, 0x64, 0x8c, 0xd6, 0x92, 0x08, 0x83, 0x12, + 0x1d, 0x6b, 0x00, 0x43, 0x70, 0x5b, 0xe7, 0x54, 0x2c, 0xa8, 0x8c, 0x79, 0x12, 0x39, 0x3b, 0x43, + 0xeb, 0xc0, 0xf6, 0x3f, 0x79, 0x56, 0xb8, 0xb5, 0xdf, 0x0b, 0x77, 0xdf, 0x78, 0x90, 0xd1, 0x93, + 0x11, 0xe3, 0x5e, 0x4a, 0x54, 0x3c, 0x7a, 0x48, 0xa7, 0x24, 0x3c, 0x3b, 0xa4, 0xe1, 0xb2, 0x70, + 0x5f, 0x5d, 0xa3, 0xbf, 0xa2, 0x40, 0xb8, 0x53, 0x06, 0x4e, 0x56, 0x18, 0x7e, 0x0b, 0x3a, 0x29, + 0x59, 0x04, 0x11, 0x9d, 0x33, 0xa2, 0x18, 0xcf, 0x9c, 0xba, 0xd6, 0xf8, 0xf8, 0x66, 0x1a, 0x5d, + 0xa3, 0xb1, 0xc1, 0x80, 0x70, 0x3b, 0x25, 0x8b, 0xc3, 0x15, 0x84, 0x0f, 0xc0, 0x1d, 0x41, 0x7f, + 0x98, 0x31, 0x41, 0xa3, 0x20, 0xa2, 0x19, 0x4f, 0xa5, 0xd3, 0x18, 0xd6, 0x0f, 0x6c, 0xbf, 0xbf, + 0x2c, 0xdc, 0x9e, 0x21, 0xd8, 0x5a, 0x80, 0xf0, 0xed, 0x55, 0xe4, 0x50, 0x07, 0xca, 0x5a, 0xc8, + 0x84, 0xc8, 0x38, 0xf8, 0x4e, 0x90, 0x50, 0xfb, 0xdc, 0xfd, 0x0f, 0xb5, 0xd8, 0xa4, 0x40, 0xb8, + 0xa3, 0x03, 0x9f, 0x55, 0x18, 0x8e, 0x41, 0xdb, 0xac, 0x38, 0x65, 0x59, 0xc4, 0x4f, 0x9d, 0xa6, + 0x6e, 0xd5, 0x6b, 0xcb, 0xc2, 0x7d, 0x65, 0x7d, 0xbf, 0xc9, 0x22, 0xdc, 0xd2, 0xf0, 0x6b, 0x8d, + 0xa0, 0x04, 0xdd, 0x94, 0x65, 0xc1, 0x9c, 0x24, 0x2c, 0x2a, 0xbb, 0xb9, 0xe2, 0xb8, 0xa5, 0x6d, + 0xfa, 0x37, 0xb3, 0xb9, 0x5f, 0x95, 0xf3, 0x1f, 0x88, 0x10, 0xbe, 0x97, 0xb2, 0xec, 0x51, 0x19, + 0x3d, 0xa6, 0xa2, 0x12, 0x7d, 0x0c, 0x5a, 0x82, 0x9e, 0x12, 0x11, 0x05, 0x13, 0x92, 0x45, 0xce, + 0x9e, 0xd6, 0xfa, 0xe8, 0x66, 0x5a, 0x70, 0x55, 0xf9, 0xab, 0xfd, 0x08, 0x03, 0x83, 0x7c, 0x92, + 0x45, 0xf0, 0x1b, 0x60, 0x9f, 0xc6, 0x4c, 0xd1, 0x84, 0x49, 0xe5, 0xd8, 0xc3, 0xfa, 0x41, 0xeb, + 0xfd, 0xee, 0x68, 0x63, 0x34, 0x46, 0xba, 0x37, 0xfe, 0xdb, 0xa5, 0xde, 0xb2, 0x70, 0xef, 0x1a, + 0xc2, 0xab, 0x4d, 0xe8, 0xe7, 0x3f, 0x5c, 0x5b, 0x2f, 0x79, 0xc8, 0xa4, 0xc2, 0xd7, 0x6c, 0x70, + 0x02, 0x5e, 0xa7, 0x8b, 0x30, 0x26, 0xd9, 0x94, 0x06, 0x82, 0x28, 0x1a, 0xc8, 0x8c, 0xe4, 0x01, + 0xcd, 0x79, 0x18, 0x4b, 0x07, 0x68, 0xa9, 0x37, 0xb7, 0xa4, 0x8e, 0x05, 0x0b, 0xe9, 0x17, 0x99, + 0xa2, 0x62, 0x4e, 0x12, 0x3d, 0x58, 0x7e, 0xa3, 0xd4, 0xc5, 0xbd, 0x15, 0x13, 0x26, 0x8a, 0x7e, + 0x95, 0x91, 0xfc, 0x48, 0xd3, 0x8c, 0xf7, 0x7e, 0x3a, 0x77, 0x6b, 0x7f, 0x9d, 0xbb, 0x16, 0x1a, + 0x83, 0x5d, 0xed, 0x02, 0xbe, 0x05, 0x1a, 0x19, 0x49, 0xa9, 0x9e, 0x40, 0xdb, 0xbf, 0xb3, 0x2c, + 0xdc, 0x96, 0xb1, 0x5c, 0x46, 0x11, 0xd6, 0xc9, 0x71, 0xfb, 0xe9, 0xb9, 0x5b, 0xab, 0xf6, 0xd6, + 0xd0, 0x2f, 0x16, 0xb8, 0x77, 0xb4, 0x26, 0x70, 0x32, 0xcb, 0x13, 0x0a, 0xdf, 0x01, 0xbb, 0xfa, + 0x3b, 0xad, 0x98, 0xee, 0x2e, 0x0b, 0xb7, 0x6d, 0x98, 0x74, 0x18, 0x61, 0x93, 0x2e, 0x67, 0x6b, + 0xe3, 0x9c, 0xd5, 0xfc, 0xbe, 0xdc, 0x6c, 0x6d, 0x30, 0x20, 0xdc, 0x5e, 0x3f, 0xef, 0x96, 0xdb, + 0x29, 0xe8, 0x3c, 0xe2, 0x8a, 0x1e, 0x2d, 0x14, 0xcd, 0x64, 0xf9, 0x41, 0xf7, 0x40, 0x33, 0xa6, + 0x6c, 0x1a, 0x2b, 0xed, 0xb4, 0x8e, 0x2b, 0x04, 0x3f, 0x05, 0xcd, 0xbc, 0x2c, 0xa8, 0x74, 0x76, + 0x74, 0xb5, 0x87, 0x5b, 0xd5, 0x7e, 0xe1, 0xc8, 0x55, 0xb1, 0xab, 0x5d, 0x88, 0x01, 0xf8, 0x62, + 0x43, 0x60, 0x17, 0xec, 0xea, 0x1e, 0x9a, 0xb2, 0x60, 0x03, 0x60, 0x1f, 0xec, 0x45, 0x33, 0x61, + 0xee, 0x96, 0x1d, 0xed, 0xe2, 0x0a, 0xc3, 0x7d, 0x60, 0x97, 0x57, 0x47, 0xc8, 0x67, 0x99, 0xd2, + 0x17, 0x4f, 0x1d, 0xef, 0xa5, 0x64, 0xf1, 0xa0, 0xc4, 0xe3, 0x86, 0xee, 0xde, 0xaf, 0x16, 0xe8, + 0x7d, 0xce, 0xa4, 0xe2, 0x82, 0x85, 0x24, 0x59, 0x37, 0xf6, 0x2f, 0x7a, 0x6f, 0x00, 0x5b, 0xb1, + 0x94, 0x4a, 0x45, 0xd2, 0xbc, 0x12, 0xbc, 0x0e, 0x5c, 0xb7, 0xae, 0xfe, 0x92, 0xad, 0x6b, 0xfc, + 0xcf, 0xad, 0xf3, 0x0f, 0x9f, 0x5d, 0x0c, 0xac, 0xe7, 0x17, 0x03, 0xeb, 0xcf, 0x8b, 0x81, 0xf5, + 0xe3, 0xe5, 0xa0, 0xf6, 0xfc, 0x72, 0x50, 0xfb, 0xed, 0x72, 0x50, 0x7b, 0xfc, 0xee, 0x94, 0xa9, + 0x78, 0x36, 0x19, 0x85, 0x3c, 0xf5, 0x4e, 0x28, 0x49, 0xdf, 0xfb, 0xd2, 0x3c, 0x56, 0x21, 0x17, + 0xd4, 0x5b, 0xac, 0xde, 0x2c, 0x75, 0x96, 0x53, 0x39, 0x69, 0xea, 0xe7, 0xe6, 0x83, 0xbf, 0x03, + 0x00, 0x00, 0xff, 0xff, 0xae, 0xd2, 0x07, 0x12, 0xd1, 0x06, 0x00, 0x00, } func (this *Params) Equal(that interface{}) bool { @@ -339,6 +478,44 @@ func (this *Params) Equal(that interface{}) bool { return false } } + if len(this.ExchangeRateSnapEpochs) != len(that1.ExchangeRateSnapEpochs) { + return false + } + for i := range this.ExchangeRateSnapEpochs { + if !this.ExchangeRateSnapEpochs[i].Equal(&that1.ExchangeRateSnapEpochs[i]) { + return false + } + } + return true +} +func (this *PriceIntervalParam) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*PriceIntervalParam) + if !ok { + that2, ok := that.(PriceIntervalParam) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Epoch != that1.Epoch { + return false + } + if this.Duration != that1.Duration { + return false + } + if this.MaxCount != that1.MaxCount { + return false + } return true } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -361,6 +538,20 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ExchangeRateSnapEpochs) > 0 { + for iNdEx := len(m.ExchangeRateSnapEpochs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ExchangeRateSnapEpochs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + } + } if len(m.Whitelist) > 0 { for iNdEx := len(m.Whitelist) - 1; iNdEx >= 0; iNdEx-- { { @@ -559,6 +750,98 @@ func (m *VoteExtension) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *PriceIntervalParam) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *PriceIntervalParam) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PriceIntervalParam) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MaxCount != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.MaxCount)) + i-- + dAtA[i] = 0x18 + } + if m.Duration != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.Duration)) + i-- + dAtA[i] = 0x10 + } + if len(m.Epoch) > 0 { + i -= len(m.Epoch) + copy(dAtA[i:], m.Epoch) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Epoch))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *HistoricalExchangeRate) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HistoricalExchangeRate) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *HistoricalExchangeRate) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.ExchangeRate.Size() + i -= size + if _, err := m.ExchangeRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintOracle(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x1a + } + if m.Timestamp != 0 { + i = encodeVarintOracle(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x10 + } + if len(m.Epoch) > 0 { + i -= len(m.Epoch) + copy(dAtA[i:], m.Epoch) + i = encodeVarintOracle(dAtA, i, uint64(len(m.Epoch))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintOracle(dAtA []byte, offset int, v uint64) int { offset -= sovOracle(v) base := offset @@ -604,6 +887,12 @@ func (m *Params) Size() (n int) { n += 1 + l + sovOracle(uint64(l)) } } + if len(m.ExchangeRateSnapEpochs) > 0 { + for _, e := range m.ExchangeRateSnapEpochs { + l = e.Size() + n += 1 + l + sovOracle(uint64(l)) + } + } return n } @@ -653,6 +942,47 @@ func (m *VoteExtension) Size() (n int) { return n } +func (m *PriceIntervalParam) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Epoch) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + if m.Duration != 0 { + n += 1 + sovOracle(uint64(m.Duration)) + } + if m.MaxCount != 0 { + n += 1 + sovOracle(uint64(m.MaxCount)) + } + return n +} + +func (m *HistoricalExchangeRate) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Epoch) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + if m.Timestamp != 0 { + n += 1 + sovOracle(uint64(m.Timestamp)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovOracle(uint64(l)) + } + l = m.ExchangeRate.Size() + n += 1 + l + sovOracle(uint64(l)) + return n +} + func sovOracle(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -962,6 +1292,40 @@ func (m *Params) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRateSnapEpochs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ExchangeRateSnapEpochs = append(m.ExchangeRateSnapEpochs, PriceIntervalParam{}) + if err := m.ExchangeRateSnapEpochs[len(m.ExchangeRateSnapEpochs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipOracle(dAtA[iNdEx:]) @@ -1284,6 +1648,293 @@ func (m *VoteExtension) Unmarshal(dAtA []byte) error { } return nil } +func (m *PriceIntervalParam) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: PriceIntervalParam: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PriceIntervalParam: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Epoch = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Duration", wireType) + } + m.Duration = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Duration |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxCount", wireType) + } + m.MaxCount = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MaxCount |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *HistoricalExchangeRate) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HistoricalExchangeRate: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HistoricalExchangeRate: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Epoch = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExchangeRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOracle + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOracle + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthOracle + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExchangeRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipOracle(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthOracle + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipOracle(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/oracle/types/query.pb.go b/x/oracle/types/query.pb.go index 1d097d22..7496329d 100644 --- a/x/oracle/types/query.pb.go +++ b/x/oracle/types/query.pb.go @@ -533,6 +533,102 @@ func (m *QueryParamsResponse) GetParams() Params { return Params{} } +type QueryHistoricalExchangeRatesRequest struct { + Epoch string `protobuf:"bytes,1,opt,name=epoch,proto3" json:"epoch,omitempty"` + Denom string `protobuf:"bytes,2,opt,name=denom,proto3" json:"denom,omitempty"` +} + +func (m *QueryHistoricalExchangeRatesRequest) Reset() { *m = QueryHistoricalExchangeRatesRequest{} } +func (m *QueryHistoricalExchangeRatesRequest) String() string { return proto.CompactTextString(m) } +func (*QueryHistoricalExchangeRatesRequest) ProtoMessage() {} +func (*QueryHistoricalExchangeRatesRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_b180a0d90a2c8cf7, []int{12} +} +func (m *QueryHistoricalExchangeRatesRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryHistoricalExchangeRatesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryHistoricalExchangeRatesRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryHistoricalExchangeRatesRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryHistoricalExchangeRatesRequest.Merge(m, src) +} +func (m *QueryHistoricalExchangeRatesRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryHistoricalExchangeRatesRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryHistoricalExchangeRatesRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryHistoricalExchangeRatesRequest proto.InternalMessageInfo + +func (m *QueryHistoricalExchangeRatesRequest) GetEpoch() string { + if m != nil { + return m.Epoch + } + return "" +} + +func (m *QueryHistoricalExchangeRatesRequest) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +type QueryHistoricalExchangeRatesResponse struct { + HistoricalRates []HistoricalExchangeRate `protobuf:"bytes,1,rep,name=historical_rates,json=historicalRates,proto3" json:"historical_rates"` +} + +func (m *QueryHistoricalExchangeRatesResponse) Reset() { *m = QueryHistoricalExchangeRatesResponse{} } +func (m *QueryHistoricalExchangeRatesResponse) String() string { return proto.CompactTextString(m) } +func (*QueryHistoricalExchangeRatesResponse) ProtoMessage() {} +func (*QueryHistoricalExchangeRatesResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b180a0d90a2c8cf7, []int{13} +} +func (m *QueryHistoricalExchangeRatesResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryHistoricalExchangeRatesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryHistoricalExchangeRatesResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryHistoricalExchangeRatesResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryHistoricalExchangeRatesResponse.Merge(m, src) +} +func (m *QueryHistoricalExchangeRatesResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryHistoricalExchangeRatesResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryHistoricalExchangeRatesResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryHistoricalExchangeRatesResponse proto.InternalMessageInfo + +func (m *QueryHistoricalExchangeRatesResponse) GetHistoricalRates() []HistoricalExchangeRate { + if m != nil { + return m.HistoricalRates + } + return nil +} + func init() { proto.RegisterType((*QueryExchangeRateRequest)(nil), "kujira.oracle.QueryExchangeRateRequest") proto.RegisterType((*QueryExchangeRateResponse)(nil), "kujira.oracle.QueryExchangeRateResponse") @@ -546,58 +642,66 @@ func init() { proto.RegisterType((*QueryMissCounterResponse)(nil), "kujira.oracle.QueryMissCounterResponse") proto.RegisterType((*QueryParamsRequest)(nil), "kujira.oracle.QueryParamsRequest") proto.RegisterType((*QueryParamsResponse)(nil), "kujira.oracle.QueryParamsResponse") + proto.RegisterType((*QueryHistoricalExchangeRatesRequest)(nil), "kujira.oracle.QueryHistoricalExchangeRatesRequest") + proto.RegisterType((*QueryHistoricalExchangeRatesResponse)(nil), "kujira.oracle.QueryHistoricalExchangeRatesResponse") } func init() { proto.RegisterFile("kujira/oracle/query.proto", fileDescriptor_b180a0d90a2c8cf7) } var fileDescriptor_b180a0d90a2c8cf7 = []byte{ - // 729 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x94, 0x4f, 0x4f, 0x13, 0x4f, - 0x18, 0xc7, 0xbb, 0xbf, 0x1f, 0x7f, 0x64, 0x4a, 0x89, 0x19, 0x0b, 0x96, 0x05, 0xb7, 0xb0, 0x08, - 0x54, 0x94, 0x1d, 0xfe, 0xdc, 0x48, 0x3c, 0x50, 0x30, 0x31, 0xa8, 0x89, 0x6e, 0x88, 0x07, 0x2f, - 0xcd, 0x74, 0x77, 0xb2, 0xac, 0xb0, 0x3b, 0x65, 0x66, 0xda, 0x40, 0x08, 0x17, 0x4f, 0x26, 0x1e, - 0x24, 0x31, 0xd1, 0x2b, 0x67, 0x5f, 0x09, 0x47, 0x12, 0x2f, 0xc6, 0x03, 0x1a, 0xf0, 0xe0, 0xcb, - 0x30, 0x9d, 0x99, 0x6d, 0xbb, 0x58, 0xc1, 0xd3, 0x74, 0x9f, 0xe7, 0x99, 0xef, 0xf3, 0xe9, 0xcc, - 0xf7, 0x19, 0x30, 0xba, 0x5d, 0x7f, 0x1d, 0x32, 0x8c, 0x28, 0xc3, 0xde, 0x0e, 0x41, 0xbb, 0x75, - 0xc2, 0xf6, 0x9d, 0x1a, 0xa3, 0x82, 0xc2, 0x9c, 0x4a, 0x39, 0x2a, 0x65, 0xe6, 0x03, 0x1a, 0x50, - 0x99, 0x41, 0xcd, 0x5f, 0xaa, 0xc8, 0x1c, 0x0f, 0x28, 0x0d, 0x76, 0x08, 0xc2, 0xb5, 0x10, 0xe1, - 0x38, 0xa6, 0x02, 0x8b, 0x90, 0xc6, 0x5c, 0x67, 0xcd, 0xb4, 0xba, 0x5a, 0x74, 0xce, 0xf2, 0x28, - 0x8f, 0x28, 0x47, 0x55, 0xcc, 0x09, 0x6a, 0x2c, 0x56, 0x89, 0xc0, 0x8b, 0xc8, 0xa3, 0x61, 0xac, - 0xf2, 0xf6, 0x0a, 0x28, 0xbc, 0x68, 0xd2, 0x3c, 0xda, 0xf3, 0xb6, 0x70, 0x1c, 0x10, 0x17, 0x0b, - 0xe2, 0x92, 0xdd, 0x3a, 0xe1, 0x02, 0xe6, 0x41, 0xaf, 0x4f, 0x62, 0x1a, 0x15, 0x8c, 0x09, 0xa3, - 0x34, 0xe0, 0xaa, 0x8f, 0x95, 0x1b, 0x6f, 0x8f, 0x8b, 0x99, 0x5f, 0xc7, 0xc5, 0x8c, 0x4d, 0xc0, - 0x68, 0x97, 0xbd, 0xbc, 0x46, 0x63, 0x4e, 0xe0, 0x63, 0x90, 0x23, 0x3a, 0x5e, 0x61, 0x58, 0x10, - 0x25, 0x52, 0x9e, 0x3a, 0x39, 0x2b, 0x66, 0xbe, 0x9d, 0x15, 0xc7, 0x14, 0x17, 0xf7, 0xb7, 0x9d, - 0x90, 0xa2, 0x08, 0x8b, 0x2d, 0xe7, 0x29, 0x09, 0xb0, 0xb7, 0xbf, 0x4e, 0x3c, 0x77, 0x90, 0x74, - 0x28, 0xda, 0x63, 0x5d, 0xda, 0x70, 0xcd, 0x68, 0x7f, 0x34, 0x80, 0xd9, 0x2d, 0xab, 0x29, 0xf6, - 0xc0, 0x50, 0x8a, 0x82, 0x17, 0x8c, 0x89, 0xff, 0x4b, 0xd9, 0xa5, 0x71, 0x47, 0xf5, 0x77, 0x9a, - 0xe7, 0xe2, 0xe8, 0x73, 0x71, 0xd6, 0x89, 0xb7, 0x46, 0xc3, 0xb8, 0xbc, 0xdc, 0x84, 0xfc, 0xfc, - 0xbd, 0x78, 0x3f, 0x08, 0xc5, 0x56, 0xbd, 0xea, 0x78, 0x34, 0x42, 0xfa, 0x1c, 0xd5, 0x32, 0xcf, - 0xfd, 0x6d, 0x24, 0xf6, 0x6b, 0x84, 0x27, 0x7b, 0xb8, 0x9b, 0xeb, 0x84, 0xe6, 0xf6, 0x30, 0xb8, - 0x25, 0xb9, 0x56, 0x3d, 0x11, 0x36, 0xda, 0xbc, 0x0b, 0x20, 0x9f, 0x0e, 0x6b, 0xd0, 0x02, 0xe8, - 0xc7, 0x2a, 0x24, 0x09, 0x07, 0xdc, 0xe4, 0xd3, 0x1e, 0x05, 0xb7, 0xe5, 0x8e, 0x97, 0x54, 0x90, - 0x4d, 0xcc, 0x02, 0x22, 0x5a, 0x62, 0x0f, 0xf5, 0xe5, 0xa5, 0x52, 0x5a, 0x70, 0x12, 0x0c, 0x36, - 0xa8, 0x20, 0x15, 0xa1, 0xe2, 0x5a, 0x35, 0xdb, 0x68, 0x97, 0xda, 0x1b, 0x5a, 0xf9, 0x59, 0xc8, - 0xf9, 0x1a, 0xad, 0xc7, 0x82, 0xb0, 0xe4, 0xea, 0xa7, 0xc1, 0x50, 0x03, 0xef, 0x84, 0x3e, 0x16, - 0x94, 0x55, 0xb0, 0xef, 0x33, 0xed, 0x81, 0x5c, 0x2b, 0xba, 0xea, 0xfb, 0xac, 0xc3, 0x0b, 0x09, - 0x4a, 0x4a, 0xab, 0x8d, 0x12, 0x85, 0x9c, 0x57, 0x3c, 0x15, 0x97, 0x52, 0x3d, 0x6e, 0x36, 0x6a, - 0x97, 0xda, 0x79, 0x00, 0xe5, 0xf6, 0xe7, 0x98, 0xe1, 0xa8, 0xf5, 0xff, 0x36, 0xf4, 0x19, 0x26, - 0x51, 0xad, 0xb7, 0x0c, 0xfa, 0x6a, 0x32, 0x22, 0x95, 0xb2, 0x4b, 0xc3, 0x4e, 0x6a, 0x86, 0x1c, - 0x55, 0x5e, 0xee, 0x69, 0xde, 0xa2, 0xab, 0x4b, 0x97, 0x3e, 0xf5, 0x82, 0x5e, 0x29, 0x06, 0xdf, - 0x1b, 0x60, 0xb0, 0xd3, 0x2d, 0x70, 0xf6, 0xd2, 0xfe, 0xbf, 0x0d, 0x84, 0x59, 0xba, 0xbe, 0x50, - 0x21, 0xda, 0x0f, 0xde, 0x7c, 0xf9, 0xf9, 0xe1, 0xbf, 0x19, 0x78, 0x37, 0x19, 0x4a, 0x39, 0x3b, - 0x1c, 0x1d, 0xc8, 0xf5, 0x10, 0xa5, 0x4c, 0x09, 0xdf, 0x19, 0x20, 0x97, 0xf2, 0x2f, 0xbc, 0xb6, - 0x53, 0x72, 0x46, 0xe6, 0xbd, 0x7f, 0xa8, 0xd4, 0x50, 0xd3, 0x12, 0xaa, 0x08, 0xef, 0x5c, 0x82, - 0x4a, 0x4f, 0x08, 0x64, 0xa0, 0x5f, 0xbb, 0x13, 0xda, 0xdd, 0xc4, 0xd3, 0x8e, 0x36, 0xa7, 0xae, - 0xac, 0xd1, 0xad, 0x2d, 0xd9, 0xba, 0x00, 0x47, 0x2e, 0xb5, 0xd6, 0x26, 0x87, 0x47, 0x06, 0xc8, - 0x76, 0x58, 0x07, 0xce, 0x74, 0x13, 0xfd, 0xd3, 0xa7, 0xe6, 0xec, 0xb5, 0x75, 0x1a, 0x60, 0x41, - 0x02, 0xcc, 0xc1, 0x52, 0x02, 0xd0, 0x32, 0x32, 0x47, 0x07, 0x69, 0xab, 0x1f, 0xa2, 0xa6, 0x33, - 0x61, 0x00, 0xfa, 0x94, 0x91, 0xe0, 0x64, 0xb7, 0x26, 0x29, 0xa7, 0x9a, 0xf6, 0x55, 0x25, 0x1a, - 0x61, 0x44, 0x22, 0xdc, 0x84, 0x43, 0x09, 0x82, 0x72, 0x66, 0x79, 0xfd, 0xe4, 0xdc, 0x32, 0x4e, - 0xcf, 0x2d, 0xe3, 0xc7, 0xb9, 0x65, 0x1c, 0x5d, 0x58, 0x99, 0xd3, 0x0b, 0x2b, 0xf3, 0xf5, 0xc2, - 0xca, 0xbc, 0x9a, 0xeb, 0x78, 0x7f, 0x36, 0x09, 0x8e, 0xe6, 0x9f, 0xa8, 0x87, 0xde, 0xa3, 0x8c, - 0xa0, 0xbd, 0x44, 0x46, 0xbe, 0x43, 0xd5, 0x3e, 0xf9, 0x9e, 0x2f, 0xff, 0x0e, 0x00, 0x00, 0xff, - 0xff, 0x91, 0x18, 0x7c, 0x6b, 0x6b, 0x06, 0x00, 0x00, + // 826 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x95, 0xcf, 0x6f, 0xe3, 0x44, + 0x14, 0xc7, 0xe3, 0x65, 0x37, 0xcb, 0x4e, 0x9a, 0xb2, 0x1a, 0xb2, 0xbb, 0xa9, 0x77, 0x71, 0xb6, + 0x4e, 0x7f, 0xa4, 0x85, 0x7a, 0xda, 0xe4, 0x56, 0x89, 0x43, 0xd3, 0x22, 0x55, 0x05, 0x24, 0x6a, + 0x55, 0x3d, 0x70, 0x89, 0x26, 0xf6, 0xc8, 0x31, 0x8d, 0x3d, 0xa9, 0x67, 0x12, 0xb5, 0xaa, 0xca, + 0x81, 0x13, 0x12, 0x07, 0x2a, 0x21, 0x71, 0xee, 0x19, 0x89, 0xbf, 0x83, 0x1e, 0x2b, 0x71, 0x41, + 0x1c, 0x0a, 0x6a, 0x39, 0xf0, 0x67, 0xa0, 0xcc, 0x8c, 0x13, 0x3b, 0xb8, 0x29, 0x9c, 0x1c, 0xbf, + 0xf7, 0xe6, 0xfb, 0x3e, 0x9e, 0x79, 0xdf, 0x0c, 0x98, 0x3b, 0xea, 0x7f, 0xe5, 0x47, 0x18, 0xd1, + 0x08, 0x3b, 0x5d, 0x82, 0x8e, 0xfb, 0x24, 0x3a, 0xb5, 0x7a, 0x11, 0xe5, 0x14, 0x16, 0x65, 0xca, + 0x92, 0x29, 0xbd, 0xe4, 0x51, 0x8f, 0x8a, 0x0c, 0x1a, 0xfe, 0x92, 0x45, 0xfa, 0x1b, 0x8f, 0x52, + 0xaf, 0x4b, 0x10, 0xee, 0xf9, 0x08, 0x87, 0x21, 0xe5, 0x98, 0xfb, 0x34, 0x64, 0x2a, 0xab, 0xa7, + 0xd5, 0xe5, 0x43, 0xe5, 0x0c, 0x87, 0xb2, 0x80, 0x32, 0xd4, 0xc6, 0x8c, 0xa0, 0xc1, 0x46, 0x9b, + 0x70, 0xbc, 0x81, 0x1c, 0xea, 0x87, 0x32, 0x6f, 0x6e, 0x82, 0xf2, 0xfe, 0x90, 0xe6, 0x93, 0x13, + 0xa7, 0x83, 0x43, 0x8f, 0xd8, 0x98, 0x13, 0x9b, 0x1c, 0xf7, 0x09, 0xe3, 0xb0, 0x04, 0x9e, 0xb8, + 0x24, 0xa4, 0x41, 0x59, 0x7b, 0xab, 0xd5, 0x9e, 0xd9, 0xf2, 0x65, 0xf3, 0xdd, 0x6f, 0x2f, 0x2b, + 0xb9, 0xbf, 0x2f, 0x2b, 0x39, 0x93, 0x80, 0xb9, 0x8c, 0xb5, 0xac, 0x47, 0x43, 0x46, 0xe0, 0x2e, + 0x28, 0x12, 0x15, 0x6f, 0x45, 0x98, 0x13, 0x29, 0xd2, 0xac, 0x5e, 0xdd, 0x54, 0x72, 0xbf, 0xdf, + 0x54, 0x5e, 0x4b, 0x2e, 0xe6, 0x1e, 0x59, 0x3e, 0x45, 0x01, 0xe6, 0x1d, 0xeb, 0x33, 0xe2, 0x61, + 0xe7, 0x74, 0x87, 0x38, 0xf6, 0x0c, 0x49, 0x28, 0x9a, 0xaf, 0x33, 0xda, 0x30, 0xc5, 0x68, 0xfe, + 0xa8, 0x01, 0x3d, 0x2b, 0xab, 0x28, 0x4e, 0xc0, 0x6c, 0x8a, 0x82, 0x95, 0xb5, 0xb7, 0xef, 0xd4, + 0x0a, 0xf5, 0x37, 0x96, 0xec, 0x6f, 0x0d, 0xf7, 0xc5, 0x52, 0xfb, 0x62, 0xed, 0x10, 0x67, 0x9b, + 0xfa, 0x61, 0xb3, 0x31, 0x84, 0xfc, 0xe9, 0x8f, 0xca, 0x87, 0x9e, 0xcf, 0x3b, 0xfd, 0xb6, 0xe5, + 0xd0, 0x00, 0xa9, 0x7d, 0x94, 0x8f, 0x35, 0xe6, 0x1e, 0x21, 0x7e, 0xda, 0x23, 0x2c, 0x5e, 0xc3, + 0xec, 0x62, 0x12, 0x9a, 0x99, 0x2f, 0xc0, 0xfb, 0x82, 0x6b, 0xcb, 0xe1, 0xfe, 0x60, 0xcc, 0xbb, + 0x0e, 0x4a, 0xe9, 0xb0, 0x02, 0x2d, 0x83, 0xa7, 0x58, 0x86, 0x04, 0xe1, 0x33, 0x3b, 0x7e, 0x35, + 0xe7, 0xc0, 0x2b, 0xb1, 0xe2, 0x90, 0x72, 0x72, 0x80, 0x23, 0x8f, 0xf0, 0x91, 0xd8, 0xc7, 0xea, + 0xf0, 0x52, 0x29, 0x25, 0x38, 0x0f, 0x66, 0x06, 0x94, 0x93, 0x16, 0x97, 0x71, 0xa5, 0x5a, 0x18, + 0x8c, 0x4b, 0xcd, 0x3d, 0xa5, 0xfc, 0xb9, 0xcf, 0xd8, 0x36, 0xed, 0x87, 0x9c, 0x44, 0xf1, 0xd1, + 0x2f, 0x82, 0xd9, 0x01, 0xee, 0xfa, 0x2e, 0xe6, 0x34, 0x6a, 0x61, 0xd7, 0x8d, 0xd4, 0x0c, 0x14, + 0x47, 0xd1, 0x2d, 0xd7, 0x8d, 0x12, 0xb3, 0x10, 0xa3, 0xa4, 0xb4, 0xc6, 0x28, 0x81, 0xcf, 0x58, + 0xcb, 0x91, 0x71, 0x21, 0xf5, 0xd8, 0x2e, 0x04, 0xe3, 0x52, 0xb3, 0x04, 0xa0, 0x58, 0xfe, 0x05, + 0x8e, 0x70, 0x30, 0xfa, 0xbe, 0x3d, 0xb5, 0x87, 0x71, 0x54, 0xe9, 0x35, 0x40, 0xbe, 0x27, 0x22, + 0x42, 0xa9, 0x50, 0x7f, 0x61, 0xa5, 0x3c, 0x64, 0xc9, 0xf2, 0xe6, 0xe3, 0xe1, 0x29, 0xda, 0xaa, + 0xd4, 0xdc, 0x07, 0x55, 0xa1, 0xb5, 0xeb, 0x33, 0x4e, 0x23, 0xdf, 0xc1, 0xdd, 0xac, 0x79, 0x1a, + 0xce, 0x3c, 0xe9, 0x51, 0xa7, 0x13, 0xcf, 0xbc, 0x78, 0x19, 0x3b, 0xe1, 0x51, 0xc2, 0x09, 0xe6, + 0xd7, 0x60, 0x61, 0xba, 0xa4, 0xe2, 0x3d, 0x04, 0xcf, 0x3b, 0xa3, 0x92, 0xd4, 0x18, 0x2e, 0x4e, + 0x90, 0x67, 0x2b, 0xa9, 0x2f, 0x79, 0x6f, 0x2c, 0x22, 0xf4, 0xeb, 0xbf, 0xe4, 0xc1, 0x13, 0x01, + 0x00, 0xbf, 0xd7, 0xc0, 0x4c, 0x72, 0x05, 0x5c, 0x9e, 0x10, 0xbe, 0xcf, 0xe3, 0x7a, 0xed, 0xe1, + 0x42, 0xf9, 0x15, 0xe6, 0x47, 0xdf, 0xfc, 0xfa, 0xd7, 0x0f, 0x8f, 0x96, 0xe0, 0x42, 0xfc, 0x3f, + 0x23, 0x36, 0x81, 0xa1, 0x33, 0xf1, 0x3c, 0x47, 0x29, 0x9f, 0xc1, 0xef, 0x34, 0x50, 0x4c, 0xed, + 0x06, 0x7c, 0xb0, 0x53, 0x7c, 0x06, 0xfa, 0xca, 0x7f, 0xa8, 0x54, 0x50, 0x8b, 0x02, 0xaa, 0x02, + 0x3f, 0x98, 0x80, 0x4a, 0x9b, 0x1e, 0x46, 0xe0, 0xa9, 0x32, 0x1c, 0x34, 0xb3, 0xc4, 0xd3, 0x26, + 0xd5, 0xab, 0x53, 0x6b, 0x54, 0x6b, 0x43, 0xb4, 0x2e, 0xc3, 0x97, 0x13, 0xad, 0x95, 0x6f, 0xe1, + 0x85, 0x06, 0x0a, 0x09, 0x37, 0xc0, 0xa5, 0x2c, 0xd1, 0x7f, 0x5b, 0x4f, 0x5f, 0x7e, 0xb0, 0x4e, + 0x01, 0xac, 0x0b, 0x80, 0x55, 0x58, 0x8b, 0x01, 0x46, 0xde, 0x64, 0xe8, 0x2c, 0xed, 0xde, 0x73, + 0x34, 0x34, 0x1b, 0xf4, 0x40, 0x5e, 0x7a, 0x03, 0xce, 0x67, 0x35, 0x49, 0x99, 0x4f, 0x37, 0xa7, + 0x95, 0x28, 0x84, 0x97, 0x02, 0xe1, 0x39, 0x9c, 0x8d, 0x11, 0xa4, 0xd9, 0xe0, 0xcf, 0x1a, 0x78, + 0x75, 0x8f, 0x2b, 0x60, 0x3d, 0x4b, 0x77, 0xba, 0x2b, 0xf5, 0xc6, 0xff, 0x5a, 0xa3, 0xe0, 0x56, + 0x04, 0x5c, 0x15, 0xce, 0xc7, 0x70, 0x09, 0x13, 0xa6, 0xe7, 0xa3, 0xb9, 0x73, 0x75, 0x6b, 0x68, + 0xd7, 0xb7, 0x86, 0xf6, 0xe7, 0xad, 0xa1, 0x5d, 0xdc, 0x19, 0xb9, 0xeb, 0x3b, 0x23, 0xf7, 0xdb, + 0x9d, 0x91, 0xfb, 0x72, 0x35, 0x71, 0x05, 0x1c, 0x10, 0x1c, 0xac, 0x7d, 0x2a, 0xef, 0x5a, 0x87, + 0x46, 0x04, 0x9d, 0xc4, 0xca, 0xe2, 0x2a, 0x68, 0xe7, 0xc5, 0x95, 0xda, 0xf8, 0x27, 0x00, 0x00, + 0xff, 0xff, 0x45, 0x9b, 0xce, 0xf2, 0xee, 0x07, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -622,6 +726,7 @@ type QueryClient interface { MissCounter(ctx context.Context, in *QueryMissCounterRequest, opts ...grpc.CallOption) (*QueryMissCounterResponse, error) // Params queries all parameters. Params(ctx context.Context, in *QueryParamsRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) + HistoricalExchangeRates(ctx context.Context, in *QueryHistoricalExchangeRatesRequest, opts ...grpc.CallOption) (*QueryHistoricalExchangeRatesResponse, error) } type queryClient struct { @@ -677,6 +782,15 @@ func (c *queryClient) Params(ctx context.Context, in *QueryParamsRequest, opts . return out, nil } +func (c *queryClient) HistoricalExchangeRates(ctx context.Context, in *QueryHistoricalExchangeRatesRequest, opts ...grpc.CallOption) (*QueryHistoricalExchangeRatesResponse, error) { + out := new(QueryHistoricalExchangeRatesResponse) + err := c.cc.Invoke(ctx, "/kujira.oracle.Query/HistoricalExchangeRates", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { // ExchangeRate returns exchange rate of a denom @@ -689,6 +803,7 @@ type QueryServer interface { MissCounter(context.Context, *QueryMissCounterRequest) (*QueryMissCounterResponse, error) // Params queries all parameters. Params(context.Context, *QueryParamsRequest) (*QueryParamsResponse, error) + HistoricalExchangeRates(context.Context, *QueryHistoricalExchangeRatesRequest) (*QueryHistoricalExchangeRatesResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -710,6 +825,9 @@ func (*UnimplementedQueryServer) MissCounter(ctx context.Context, req *QueryMiss func (*UnimplementedQueryServer) Params(ctx context.Context, req *QueryParamsRequest) (*QueryParamsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Params not implemented") } +func (*UnimplementedQueryServer) HistoricalExchangeRates(ctx context.Context, req *QueryHistoricalExchangeRatesRequest) (*QueryHistoricalExchangeRatesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method HistoricalExchangeRates not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -805,6 +923,24 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf return interceptor(ctx, in, info, handler) } +func _Query_HistoricalExchangeRates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryHistoricalExchangeRatesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).HistoricalExchangeRates(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/kujira.oracle.Query/HistoricalExchangeRates", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).HistoricalExchangeRates(ctx, req.(*QueryHistoricalExchangeRatesRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "kujira.oracle.Query", HandlerType: (*QueryServer)(nil), @@ -829,6 +965,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "Params", Handler: _Query_Params_Handler, }, + { + MethodName: "HistoricalExchangeRates", + Handler: _Query_HistoricalExchangeRates_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "kujira/oracle/query.proto", @@ -1181,6 +1321,80 @@ func (m *QueryParamsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *QueryHistoricalExchangeRatesRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryHistoricalExchangeRatesRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryHistoricalExchangeRatesRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0x12 + } + if len(m.Epoch) > 0 { + i -= len(m.Epoch) + copy(dAtA[i:], m.Epoch) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Epoch))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryHistoricalExchangeRatesResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryHistoricalExchangeRatesResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryHistoricalExchangeRatesResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.HistoricalRates) > 0 { + for iNdEx := len(m.HistoricalRates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.HistoricalRates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -1333,6 +1547,38 @@ func (m *QueryParamsResponse) Size() (n int) { return n } +func (m *QueryHistoricalExchangeRatesRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Epoch) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryHistoricalExchangeRatesResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.HistoricalRates) > 0 { + for _, e := range m.HistoricalRates { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -2187,6 +2433,204 @@ func (m *QueryParamsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryHistoricalExchangeRatesRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryHistoricalExchangeRatesRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryHistoricalExchangeRatesRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Epoch", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Epoch = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Denom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryHistoricalExchangeRatesResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryHistoricalExchangeRatesResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryHistoricalExchangeRatesResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HistoricalRates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HistoricalRates = append(m.HistoricalRates, HistoricalExchangeRate{}) + if err := m.HistoricalRates[len(m.HistoricalRates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/oracle/types/query.pb.gw.go b/x/oracle/types/query.pb.gw.go index d54f1186..ea3e1085 100644 --- a/x/oracle/types/query.pb.gw.go +++ b/x/oracle/types/query.pb.gw.go @@ -193,6 +193,42 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal } +var ( + filter_Query_HistoricalExchangeRates_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_HistoricalExchangeRates_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHistoricalExchangeRatesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_HistoricalExchangeRates_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.HistoricalExchangeRates(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_HistoricalExchangeRates_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryHistoricalExchangeRatesRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_HistoricalExchangeRates_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.HistoricalExchangeRates(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterQueryHandlerServer registers the http handlers for service Query to "mux". // UnaryRPC :call QueryServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -299,6 +335,26 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv }) + mux.Handle("GET", pattern_Query_HistoricalExchangeRates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_HistoricalExchangeRates_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_HistoricalExchangeRates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -440,6 +496,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie }) + mux.Handle("GET", pattern_Query_HistoricalExchangeRates_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_HistoricalExchangeRates_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_HistoricalExchangeRates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -453,6 +529,8 @@ var ( pattern_Query_MissCounter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"oracle", "validators", "validator_addr", "miss"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"oracle", "params"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_HistoricalExchangeRates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"oracle", "historical_exchange_rates"}, "", runtime.AssumeColonVerbOpt(true))) ) var ( @@ -465,4 +543,6 @@ var ( forward_Query_MissCounter_0 = runtime.ForwardResponseMessage forward_Query_Params_0 = runtime.ForwardResponseMessage + + forward_Query_HistoricalExchangeRates_0 = runtime.ForwardResponseMessage ) From cf09512172a20d1fd6b7939c912ebee0627092e0 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 7 May 2024 20:21:35 +0800 Subject: [PATCH 3/5] add unit test for historical rate basic functions --- x/oracle/keeper/historical_rates_test.go | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 x/oracle/keeper/historical_rates_test.go diff --git a/x/oracle/keeper/historical_rates_test.go b/x/oracle/keeper/historical_rates_test.go new file mode 100644 index 00000000..e1bc9099 --- /dev/null +++ b/x/oracle/keeper/historical_rates_test.go @@ -0,0 +1,62 @@ +package keeper + +import ( + "testing" + "time" + + "cosmossdk.io/math" + "github.com/Team-Kujira/core/x/oracle/types" + "github.com/stretchr/testify/require" +) + +func TestHistoricalRates(t *testing.T) { + input := CreateTestInput(t) + + now := time.Now() + historicalRates := []types.HistoricalExchangeRate{ + { + Epoch: "day", + Timestamp: now.Unix() - 86400, + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(64000), + }, + { + Epoch: "day", + Timestamp: now.Unix(), + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(63588), + }, + { + Epoch: "hour", + Timestamp: now.Unix() - 3600, + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(63800), + }, + { + Epoch: "hour", + Timestamp: now.Unix(), + Denom: "BTC", + ExchangeRate: math.LegacyNewDec(63588), + }, + } + for _, rate := range historicalRates { + input.OracleKeeper.SetHistoricalExchangeRate(input.Ctx, rate) + } + + for _, rate := range historicalRates { + storedRate, err := input.OracleKeeper.GetHistoricalExchangeRate(input.Ctx, rate.Epoch, rate.Denom, rate.Timestamp) + require.NoError(t, err) + require.Equal(t, storedRate.ExchangeRate.String(), rate.ExchangeRate.String()) + } + + rate := input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), historicalRates[0].ExchangeRate.String()) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), historicalRates[1].ExchangeRate.String()) + + input.OracleKeeper.DeleteHistoricalExchangeRate(input.Ctx, historicalRates[0]) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), historicalRates[1].ExchangeRate.String()) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), historicalRates[1].ExchangeRate.String()) +} From 5f8a62d102a735eaa0017583f2daa0c207ec1668 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 7 May 2024 20:37:26 +0800 Subject: [PATCH 4/5] add unit test for oracle endblocker --- x/oracle/keeper/abci.go | 2 +- x/oracle/keeper/abci_test.go | 83 ++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 x/oracle/keeper/abci_test.go diff --git a/x/oracle/keeper/abci.go b/x/oracle/keeper/abci.go index f5225e89..6c01819a 100644 --- a/x/oracle/keeper/abci.go +++ b/x/oracle/keeper/abci.go @@ -18,7 +18,7 @@ func (k Keeper) EndBlocker(ctx sdk.Context) error { for _, epoch := range params.ExchangeRateSnapEpochs { for _, denom := range params.RequiredDenoms { latestRate := k.LatestHistoricalExchangeRateByEpochDenom(ctx, epoch.Epoch, denom) - if latestRate.Timestamp == 0 || latestRate.Timestamp+epoch.Duration < ctx.BlockTime().Unix() { + if latestRate.Timestamp == 0 || latestRate.Timestamp+epoch.Duration <= ctx.BlockTime().Unix() { rate, err := k.GetExchangeRate(ctx, denom) if err == nil { latestRate = types.HistoricalExchangeRate{ diff --git a/x/oracle/keeper/abci_test.go b/x/oracle/keeper/abci_test.go new file mode 100644 index 00000000..64c013d6 --- /dev/null +++ b/x/oracle/keeper/abci_test.go @@ -0,0 +1,83 @@ +package keeper + +import ( + "testing" + "time" + + "cosmossdk.io/math" + "github.com/Team-Kujira/core/x/oracle/types" + "github.com/stretchr/testify/require" +) + +func TestEndBlocker(t *testing.T) { + input := CreateTestInput(t) + + now := time.Now() + params := input.OracleKeeper.GetParams(input.Ctx) + params.RequiredDenoms = []string{"BTC"} + params.ExchangeRateSnapEpochs = []types.PriceIntervalParam{ + { + Epoch: "day", + Duration: 86400, + MaxCount: 3, + }, + { + Epoch: "hour", + Duration: 3600, + MaxCount: 3, + }, + } + input.OracleKeeper.SetParams(input.Ctx, params) + + // Run endblocker now + input.Ctx = input.Ctx.WithBlockTime(now) + input.OracleKeeper.SetExchangeRate(input.Ctx, "BTC", math.LegacyNewDec(63500)) + input.OracleKeeper.EndBlocker(input.Ctx) + rate := input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + + // Price changes after 1 hour + input.Ctx = input.Ctx.WithBlockTime(now.Add(time.Hour)) + input.OracleKeeper.SetExchangeRate(input.Ctx, "BTC", math.LegacyNewDec(63800)) + input.OracleKeeper.EndBlocker(input.Ctx) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63800).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + + // Price changes after 2 hours + input.Ctx = input.Ctx.WithBlockTime(now.Add(time.Hour * 2)) + input.OracleKeeper.SetExchangeRate(input.Ctx, "BTC", math.LegacyNewDec(64000)) + input.OracleKeeper.EndBlocker(input.Ctx) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(64000).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + + // Price changes after 1 day + input.Ctx = input.Ctx.WithBlockTime(now.Add(time.Hour * 24)) + input.OracleKeeper.SetExchangeRate(input.Ctx, "BTC", math.LegacyNewDec(64500)) + input.OracleKeeper.EndBlocker(input.Ctx) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(64500).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "day", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63500).String()) + rate = input.OracleKeeper.LatestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(64500).String()) + rate = input.OracleKeeper.OldestHistoricalExchangeRateByEpochDenom(input.Ctx, "hour", "BTC") + require.Equal(t, rate.ExchangeRate.String(), math.LegacyNewDec(63800).String()) +} From 3bb18ae1c9fbc44b8117cf3bcd0708a24bd3c4a4 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 9 May 2024 01:18:39 +0800 Subject: [PATCH 5/5] Add DefaultExchangeRateSnapEpochs for oracle historical prices --- x/oracle/client/cli/query.go | 1 + x/oracle/types/params.go | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/x/oracle/client/cli/query.go b/x/oracle/client/cli/query.go index 1501ffd9..d4518345 100644 --- a/x/oracle/client/cli/query.go +++ b/x/oracle/client/cli/query.go @@ -28,6 +28,7 @@ func GetQueryCmd() *cobra.Command { GetCmdQueryActives(), GetCmdQueryParams(), GetCmdQueryMissCounter(), + GetCmdQueryHistoricalExchangeRates(), ) return oracleQueryCmd diff --git a/x/oracle/types/params.go b/x/oracle/types/params.go index 4df17875..ff3c17aa 100644 --- a/x/oracle/types/params.go +++ b/x/oracle/types/params.go @@ -32,11 +32,12 @@ const ( // Default parameter values var ( - DefaultVoteThreshold = math.LegacyNewDecWithPrec(50, 2) // 50% - DefaultMaxDeviation = math.LegacyNewDecWithPrec(2, 1) // 2% (-1, 1) - DefaultRequiredDenoms = []string{} - DefaultSlashFraction = math.LegacyNewDecWithPrec(1, 4) // 0.01% - DefaultMinValidPerWindow = math.LegacyNewDecWithPrec(5, 2) // 5% + DefaultVoteThreshold = math.LegacyNewDecWithPrec(50, 2) // 50% + DefaultMaxDeviation = math.LegacyNewDecWithPrec(2, 1) // 2% (-1, 1) + DefaultRequiredDenoms = []string{} + DefaultSlashFraction = math.LegacyNewDecWithPrec(1, 4) // 0.01% + DefaultMinValidPerWindow = math.LegacyNewDecWithPrec(5, 2) // 5% + DefaultExchangeRateSnapEpochs = []PriceIntervalParam{{Epoch: "min", Duration: 60, MaxCount: 3}} ) var _ paramstypes.ParamSet = &Params{} @@ -44,13 +45,14 @@ var _ paramstypes.ParamSet = &Params{} // DefaultParams creates default oracle module parameters func DefaultParams() Params { return Params{ - VotePeriod: DefaultVotePeriod, - VoteThreshold: DefaultVoteThreshold, - MaxDeviation: DefaultMaxDeviation, - RequiredDenoms: DefaultRequiredDenoms, - SlashFraction: DefaultSlashFraction, - SlashWindow: DefaultSlashWindow, - MinValidPerWindow: DefaultMinValidPerWindow, + VotePeriod: DefaultVotePeriod, + VoteThreshold: DefaultVoteThreshold, + MaxDeviation: DefaultMaxDeviation, + RequiredDenoms: DefaultRequiredDenoms, + SlashFraction: DefaultSlashFraction, + SlashWindow: DefaultSlashWindow, + MinValidPerWindow: DefaultMinValidPerWindow, + ExchangeRateSnapEpochs: DefaultExchangeRateSnapEpochs, } }