diff --git a/proto/kujira/oracle/extension.proto b/proto/kujira/oracle/extension.proto new file mode 100644 index 00000000..18d477b1 --- /dev/null +++ b/proto/kujira/oracle/extension.proto @@ -0,0 +1,28 @@ +syntax = "proto3"; +package kujira.oracle; + +import "gogoproto/gogo.proto"; +import "kujira/oracle/genesis.proto"; +import "tendermint/abci/types.proto"; + +option go_package = "github.com/Team-Kujira/core/x/oracle/types"; + +message DenomPrice { + string denom = 1; + string price = 2 [ + (gogoproto.nullable) = false, + (gogoproto.customtype) = "cosmossdk.io/math.Int" + ]; +} + +message VoteExtension { + int64 height = 1; + repeated DenomPrice prices = 2 [ (gogoproto.nullable) = false ]; +} + +// VoteExtensionTx defines vote extension execution tx +message VoteExtensionTx { + repeated DenomPrice stake_weighted_prices = 1 [ (gogoproto.nullable) = false ]; + MissCounter miss_counter = 2 [ (gogoproto.nullable) = false ]; + tendermint.abci.ExtendedCommitInfo extended_commit_info = 3 [ (gogoproto.nullable) = false ]; +} diff --git a/x/oracle/abci/proposal.go b/x/oracle/abci/proposal.go index 9169fad6..ce67de7e 100644 --- a/x/oracle/abci/proposal.go +++ b/x/oracle/abci/proposal.go @@ -16,6 +16,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/mempool" "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/gogoproto/proto" ) // StakeWeightedPrices defines the structure a proposer should use to calculate @@ -248,13 +249,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 := proto.Unmarshal(v.VoteExtension, &voteExt); 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 _, denomPrice := range voteExt.Prices { + base := denomPrice.Denom + price := math.LegacyNewDecFromBigIntWithPrec(denomPrice.Price.BigInt(), math.LegacyPrecision) 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 a155b3eb..86ca661c 100644 --- a/x/oracle/abci/proposal_test.go +++ b/x/oracle/abci/proposal_test.go @@ -17,7 +17,6 @@ import ( "github.com/Team-Kujira/core/x/oracle/keeper" cometabci "github.com/cometbft/cometbft/abci/types" cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" - tmproto "github.com/cometbft/cometbft/proto/tendermint/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -79,23 +78,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.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25000).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2200).BigInt()), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25030).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2180).BigInt()), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := proto.Marshal(&voteExt1) require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := proto.Marshal(&voteExt2) require.NoError(t, err) consAddrMap := map[string]sdk.ValAddress{ @@ -158,23 +169,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.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25000).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2200).BigInt()), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25030).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2180).BigInt()), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := proto.Marshal(&voteExt1) require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := proto.Marshal(&voteExt2) require.NoError(t, err) params := types.DefaultParams() @@ -200,6 +223,7 @@ func TestComputeStakeWeightedPricesAndMissMap(t *testing.T) { }, }) + require.NoError(t, err) require.Equal(t, math.LegacyNewDec(2180).String(), stakeWeightedPrices["ETH"].String()) require.Equal(t, math.LegacyNewDec(25000).String(), stakeWeightedPrices["BTC"].String()) require.Nil(t, missMap[ValAddrs[0].String()]) @@ -393,7 +417,7 @@ func TestPrepareProposal(t *testing.T) { handler := h.PrepareProposal() consParams := input.Ctx.ConsensusParams() - consParams.Abci = &tmproto.ABCIParams{ + consParams.Abci = &cmtproto.ABCIParams{ VoteExtensionsEnableHeight: 1, } input.Ctx = input.Ctx.WithConsensusParams(consParams) @@ -434,23 +458,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.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25000).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2200).BigInt()), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25030).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2180).BigInt()), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := proto.Marshal(&voteExt1) require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := proto.Marshal(&voteExt2) require.NoError(t, err) marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { var buf bytes.Buffer @@ -569,29 +605,41 @@ func TestProcessProposal(t *testing.T) { handler := h.ProcessProposal() consParams := input.Ctx.ConsensusParams() - consParams.Abci = &tmproto.ABCIParams{ + consParams.Abci = &cmtproto.ABCIParams{ VoteExtensionsEnableHeight: 2, } 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.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25000).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2200).BigInt()), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25030).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2180).BigInt()), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := proto.Marshal(&voteExt1) require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := proto.Marshal(&voteExt2) require.NoError(t, err) marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { var buf bytes.Buffer @@ -772,29 +820,41 @@ func TestPreBlocker(t *testing.T) { require.NoError(t, err) consParams := input.Ctx.ConsensusParams() - consParams.Abci = &tmproto.ABCIParams{ + consParams.Abci = &cmtproto.ABCIParams{ VoteExtensionsEnableHeight: 2, } 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.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25000).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2200).BigInt()), + }, }, } - voteExt2 := abci.OracleVoteExtension{ + voteExt2 := types.VoteExtension{ Height: 1, - Prices: map[string]math.LegacyDec{ - "BTC": math.LegacyNewDec(25030), - "ETH": math.LegacyNewDec(2180), + Prices: []types.DenomPrice{ + { + Denom: "BTC", + Price: math.NewIntFromBigInt(math.LegacyNewDec(25030).BigInt()), + }, + { + Denom: "ETH", + Price: math.NewIntFromBigInt(math.LegacyNewDec(2180).BigInt()), + }, }, } - voteExt1Bytes, err := json.Marshal(voteExt1) + voteExt1Bytes, err := proto.Marshal(&voteExt1) require.NoError(t, err) - voteExt2Bytes, err := json.Marshal(voteExt2) + voteExt2Bytes, err := proto.Marshal(&voteExt2) require.NoError(t, err) marshalDelimitedFn := func(msg proto.Message) ([]byte, error) { var buf bytes.Buffer @@ -896,3 +956,80 @@ func TestPreBlocker(t *testing.T) { val2MissCount := input.OracleKeeper.GetMissCounter(input.Ctx, ValAddrs[2]) require.Equal(t, val2MissCount, uint64(1)) } + +// Add unit test for miss counters +// Need to verify 3 cases: +// 1. Outliers count as a miss (> 1 standard deviation I think atm?) +// a. We need to verify this against VP - if > 66% of VP are submitting prices, then we can measure 1 SD and find the outlier misses +// b. If < 66% VP are submitting prices, there's no price recorded, but validators providing a price do not get a miss (as we can't compare their submission against a 66$% measured price) +// 2. No price counts as a miss +// Also think we log 1 miss per price. so if there are 2 expected and you don't submit any, you get 2 misses + +// set up some validators, some which have a price-feeder running, some which don't +// and see what happens as the total VP that does/doesn't changes +// let's use the same setup as devnet +// but the VE implmenetation is causing a consensus failure somehow +// we need to reproduce it +// yeah maybe set up a few cases with different configurations of VP, price-feeder runinng/not running, node running/not running + +// CROSNEST issue +// Feb 13 17:34:03 Juno-testnet kujira-dev[783901]: #033[90m5:34PM#033[0m #033[1m#033[31mERR#033[0m#033[0m CONSENSUS FAILURE!!! #033[36merr=#033[0m"version does not exist" #033[36mmodule=#033[0mconsensus #033[36mstack=#033[0m"goroutine 333 [running]: +// runtime/debug.Stack() +// \t/usr/local/go1.21.6/src/runtime/debug/stack.go:24 +0x5e +// github.com/cometbft/cometbft/consensus.(*State).receiveRoutine.func2() +// \t/srv/kujira-dev/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:800 +0x46 +// panic({0x2929880?, 0x528cb60?}) +// \t/usr/local/go1.21.6/src/runtime/panic.go:914 +0x21f +// cosmossdk.io/store/rootmulti.(*Store).Commit(0xc0006dec00) +// \t/srv/kujira-dev/go/pkg/mod/cosmossdk.io/store@v1.0.0/rootmulti/store.go:487 +0x4af +// github.com/cosmos/cosmos-sdk/baseapp.(*BaseApp).Commit(0xc00170a6c0) +// \t/srv/kujira-dev/go/pkg/mod/github.com/cosmos/cosmos-sdk@v0.50.1/baseapp/abci.go:916 +0x282 +// github.com/cosmos/cosmos-sdk/server.cometABCIWrapper.Commit(...) +// \t/srv/kujira-dev/go/pkg/mod/github.com/cosmos/cosmos-sdk@v0.50.1/server/cmt_abci.go:56 +// github.com/cometbft/cometbft/abci/client.(*localClient).Commit(0xc000ae6f40?, {0x3859a58?, 0x542c800?}, 0x0?) +// \t/srv/kujira-dev/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/abci/client/local_client.go:113 +0xd0 +// github.com/cometbft/cometbft/proxy.(*appConnConsensus).Commit(0xc000181938, {0x3859a58, 0x542c800}) +// \t/srv/kujira-dev/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/proxy/app_conn.go:109 +0x165 + +// PFC issue +// non-recoverable error when signing vote (5245/0)" [36mmodule=[0mconsensus [36mstack=[0m"goroutine 6928 [running]: +// runtime/debug.Stack() +// \t/usr/local/go/src/runtime/debug/stack.go:24 +0x5e +// github.com/cometbft/cometbft/consensus.(*State).receiveRoutine.func2() +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:800 +0x46 +// panic({0x3355700?, 0xc00ffd4ee0?}) +// \t/usr/local/go/src/runtime/panic.go:914 +0x21f +// github.com/cometbft/cometbft/consensus.(*State).signVote(0xc00118ce00, 0x2, {0xc00f97f0a0, 0x20, 0x20}, {0xdc24bc?, {0xc014cb8ee0?, 0xc005da72ec?, 0x363c6a0?}}, 0xc0153d2780) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:2387 +0x639 +// github.com/cometbft/cometbft/consensus.(*State).signAddVote(0xc00118ce00, 0x0?, {0xc00f97f0a0, 0x20, 0x20}, {0x1?, {0xc014cb8ee0?, 0xc014f83ce0?, 0x20?}}, 0xc0153d2780) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:2438 +0x212 +// github.com/cometbft/cometbft/consensus.(*State).enterPrecommit(0xc00118ce00, 0x147d, 0x0) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:1536 +0x1337 +// github.com/cometbft/cometbft/consensus.(*State).addVote(0xc00118ce00, 0xc017057450, {0x0, 0x0}) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:2295 +0x186f +// github.com/cometbft/cometbft/consensus.(*State).tryAddVote(0xc00118ce00, 0xc017057450, {0x0?, 0x4caa90?}) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:2055 +0x26 +// github.com/cometbft/cometbft/consensus.(*State).handleMsg(0xc00118ce00, {{0x431d420, 0xc014e2d108}, {0x0, 0x0}}) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:928 +0x3ce +// github.com/cometbft/cometbft/consensus.(*State).receiveRoutine(0xc00118ce00, 0x0) +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:855 +0x4bc +// created by github.com/cometbft/cometbft/consensus.(*State).OnStart in goroutine 113 +// \t/go/pkg/mod/github.com/cometbft/cometbft@v0.38.0/consensus/state.go:397 +0x10c + +// isPrecommit := vote.Type == cmtproto.PrecommitType +// if !isPrecommit && extensionsEnabled { +// // Non-recoverable because the caller passed parameters that don't make sense +// return false, fmt.Errorf("only Precommit votes may have extensions enabled; vote type: %d", vote.Type) +// } + +// isNil := vote.BlockID.IsZero() +// extSignature := (len(v.ExtensionSignature) > 0) +// if extSignature == (!isPrecommit || isNil) { +// // Non-recoverable because the vote is malformed +// return false, fmt.Errorf( +// "extensions must be present IFF vote is a non-nil Precommit; present %t, vote type %d, is nil %t", +// extSignature, +// vote.Type, +// isNil, +// ) +// } diff --git a/x/oracle/abci/vote_extensions.go b/x/oracle/abci/vote_extensions.go index 5ac059ab..e30fdcdf 100644 --- a/x/oracle/abci/vote_extensions.go +++ b/x/oracle/abci/vote_extensions.go @@ -10,8 +10,10 @@ 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" + "github.com/cosmos/gogoproto/proto" ) type VoteExtHandler struct { @@ -32,12 +34,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 +45,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.DenomPrice{}, } // Encode vote extension to bytes - emptyVoteExtBz, err := json.Marshal(emptyVoteExt) + emptyVoteExtBz, err := proto.Marshal(&emptyVoteExt) if err != nil { return nil, fmt.Errorf("failed to marshal vote extension: %w", err) } @@ -80,10 +76,16 @@ func (h *VoteExtHandler) ExtendVoteHandler(oracleConfig OracleConfig) sdk.Extend return &abci.ResponseExtendVote{VoteExtension: emptyVoteExtBz}, nil } - computedPrices := prices.Prices + computedPrices := []types.DenomPrice{} + for denom, price := range prices.Prices { + computedPrices = append(computedPrices, types.DenomPrice{ + Denom: denom, + Price: math.NewIntFromBigInt(price.BigInt()), + }) + } // produce a canonical vote extension - voteExt := OracleVoteExtension{ + voteExt := types.VoteExtension{ Height: req.Height, Prices: computedPrices, } @@ -91,7 +93,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 := proto.Marshal(&voteExt) if err != nil { return nil, fmt.Errorf("failed to marshal vote extension: %w", err) } @@ -102,13 +104,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 := proto.Unmarshal(req.VoteExtension, &voteExt) 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 +131,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.DenomPrice) error { return nil } diff --git a/x/oracle/abci/vote_extensions_test.go b/x/oracle/abci/vote_extensions_test.go index 3a5d617c..ff0d2623 100644 --- a/x/oracle/abci/vote_extensions_test.go +++ b/x/oracle/abci/vote_extensions_test.go @@ -7,9 +7,12 @@ 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/cosmos/gogoproto/proto" "github.com/stretchr/testify/require" ) @@ -44,7 +47,19 @@ 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 = proto.Unmarshal(res.VoteExtension, &voteExt) + require.NoError(t, err) + require.Len(t, voteExt.Prices, 3) + + prices := make(map[string]math.LegacyDec) + for _, price := range voteExt.Prices { + prices[price.Denom] = math.LegacyNewDecFromBigIntWithPrec(price.Price.BigInt(), math.LegacyPrecision) + } + require.Equal(t, prices["BTC"].String(), "47375.706652541026694000") + require.Equal(t, prices["ETH"].String(), "2649.328939436595054949") + require.Equal(t, prices["USDT"].String(), "1.000661260343873178") } func TestVerifyVoteExtensionHandler(t *testing.T) { @@ -61,11 +76,37 @@ func TestVerifyVoteExtensionHandler(t *testing.T) { Endpoint: testServer.URL, }) + btcPrice, ok := math.NewIntFromString("47375706652541026694000") + require.True(t, ok) + ethPrice, ok := math.NewIntFromString("2649328939436595054949") + require.True(t, ok) + usdtPrice, ok := math.NewIntFromString("1000661260343873178") + require.True(t, ok) + voteExt := types.VoteExtension{ + Height: 3, + Prices: []types.DenomPrice{ + { + Denom: "BTC", + Price: btcPrice, + }, + { + Denom: "ETH", + Price: ethPrice, + }, + { + Denom: "USDT", + Price: usdtPrice, + }, + }, + } + voteExtBytes, err := proto.Marshal(&voteExt) + 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: voteExtBytes, ValidatorAddress: []byte{}, }) require.NoError(t, err) @@ -75,7 +116,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: voteExtBytes, ValidatorAddress: []byte{}, }) require.Error(t, err) diff --git a/x/oracle/types/extension.pb.go b/x/oracle/types/extension.pb.go new file mode 100644 index 00000000..cd8c63dc --- /dev/null +++ b/x/oracle/types/extension.pb.go @@ -0,0 +1,884 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: kujira/oracle/extension.proto + +package types + +import ( + cosmossdk_io_math "cosmossdk.io/math" + fmt "fmt" + types "github.com/cometbft/cometbft/abci/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type DenomPrice struct { + Denom string `protobuf:"bytes,1,opt,name=denom,proto3" json:"denom,omitempty"` + Price cosmossdk_io_math.Int `protobuf:"bytes,2,opt,name=price,proto3,customtype=cosmossdk.io/math.Int" json:"price"` +} + +func (m *DenomPrice) Reset() { *m = DenomPrice{} } +func (m *DenomPrice) String() string { return proto.CompactTextString(m) } +func (*DenomPrice) ProtoMessage() {} +func (*DenomPrice) Descriptor() ([]byte, []int) { + return fileDescriptor_fbcc462c4867c7ca, []int{0} +} +func (m *DenomPrice) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DenomPrice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DenomPrice.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 *DenomPrice) XXX_Merge(src proto.Message) { + xxx_messageInfo_DenomPrice.Merge(m, src) +} +func (m *DenomPrice) XXX_Size() int { + return m.Size() +} +func (m *DenomPrice) XXX_DiscardUnknown() { + xxx_messageInfo_DenomPrice.DiscardUnknown(m) +} + +var xxx_messageInfo_DenomPrice proto.InternalMessageInfo + +func (m *DenomPrice) GetDenom() string { + if m != nil { + return m.Denom + } + return "" +} + +type VoteExtension struct { + Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` + Prices []DenomPrice `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_fbcc462c4867c7ca, []int{1} +} +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() []DenomPrice { + if m != nil { + return m.Prices + } + return nil +} + +// VoteExtensionTx defines vote extension execution tx +type VoteExtensionTx struct { + StakeWeightedPrices []DenomPrice `protobuf:"bytes,1,rep,name=stake_weighted_prices,json=stakeWeightedPrices,proto3" json:"stake_weighted_prices"` + MissCounter MissCounter `protobuf:"bytes,2,opt,name=miss_counter,json=missCounter,proto3" json:"miss_counter"` + ExtendedCommitInfo types.ExtendedCommitInfo `protobuf:"bytes,3,opt,name=extended_commit_info,json=extendedCommitInfo,proto3" json:"extended_commit_info"` +} + +func (m *VoteExtensionTx) Reset() { *m = VoteExtensionTx{} } +func (m *VoteExtensionTx) String() string { return proto.CompactTextString(m) } +func (*VoteExtensionTx) ProtoMessage() {} +func (*VoteExtensionTx) Descriptor() ([]byte, []int) { + return fileDescriptor_fbcc462c4867c7ca, []int{2} +} +func (m *VoteExtensionTx) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VoteExtensionTx) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VoteExtensionTx.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 *VoteExtensionTx) XXX_Merge(src proto.Message) { + xxx_messageInfo_VoteExtensionTx.Merge(m, src) +} +func (m *VoteExtensionTx) XXX_Size() int { + return m.Size() +} +func (m *VoteExtensionTx) XXX_DiscardUnknown() { + xxx_messageInfo_VoteExtensionTx.DiscardUnknown(m) +} + +var xxx_messageInfo_VoteExtensionTx proto.InternalMessageInfo + +func (m *VoteExtensionTx) GetStakeWeightedPrices() []DenomPrice { + if m != nil { + return m.StakeWeightedPrices + } + return nil +} + +func (m *VoteExtensionTx) GetMissCounter() MissCounter { + if m != nil { + return m.MissCounter + } + return MissCounter{} +} + +func (m *VoteExtensionTx) GetExtendedCommitInfo() types.ExtendedCommitInfo { + if m != nil { + return m.ExtendedCommitInfo + } + return types.ExtendedCommitInfo{} +} + +func init() { + proto.RegisterType((*DenomPrice)(nil), "kujira.oracle.DenomPrice") + proto.RegisterType((*VoteExtension)(nil), "kujira.oracle.VoteExtension") + proto.RegisterType((*VoteExtensionTx)(nil), "kujira.oracle.VoteExtensionTx") +} + +func init() { proto.RegisterFile("kujira/oracle/extension.proto", fileDescriptor_fbcc462c4867c7ca) } + +var fileDescriptor_fbcc462c4867c7ca = []byte{ + // 414 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x93, 0x96, 0x55, 0xc2, 0x65, 0x42, 0x32, 0x1d, 0x0a, 0x45, 0xcb, 0xa6, 0x72, 0x99, + 0x90, 0xb0, 0xa5, 0xed, 0xc0, 0x7d, 0xdd, 0x0e, 0x13, 0x42, 0x42, 0x61, 0x62, 0x12, 0x1c, 0x42, + 0xea, 0xbc, 0x26, 0xa6, 0xd8, 0xaf, 0x8a, 0x5d, 0x51, 0xbe, 0x01, 0x47, 0x3e, 0x56, 0x8f, 0x3d, + 0x22, 0x0e, 0x15, 0x6a, 0xbf, 0x08, 0x8a, 0xe3, 0xaa, 0x2a, 0x5c, 0x76, 0xcb, 0xf3, 0xff, 0xff, + 0x7e, 0xce, 0xf3, 0xfb, 0x93, 0xe3, 0xc9, 0xec, 0x8b, 0xac, 0x32, 0x8e, 0x55, 0x26, 0xbe, 0x02, + 0x87, 0xb9, 0x05, 0x6d, 0x24, 0x6a, 0x36, 0xad, 0xd0, 0x22, 0x3d, 0x6c, 0x64, 0xd6, 0xc8, 0xfd, + 0x5e, 0x81, 0x05, 0x3a, 0x85, 0xd7, 0x5f, 0x8d, 0xa9, 0xff, 0x7c, 0x9f, 0x51, 0x80, 0x06, 0x23, + 0xcd, 0x56, 0xb4, 0xa0, 0x73, 0xa8, 0x94, 0xd4, 0x96, 0x67, 0x23, 0x21, 0xb9, 0xfd, 0x3e, 0x05, + 0x2f, 0x0e, 0xee, 0x08, 0xb9, 0x02, 0x8d, 0xea, 0x5d, 0x25, 0x05, 0xd0, 0x1e, 0x39, 0xc8, 0xeb, + 0x2a, 0x0a, 0x4f, 0xc3, 0xb3, 0x87, 0x49, 0x53, 0xd0, 0x0b, 0x72, 0x30, 0xad, 0xe5, 0xa8, 0x55, + 0x9f, 0x5e, 0x1e, 0x2f, 0x56, 0x27, 0xc1, 0xef, 0xd5, 0xc9, 0x91, 0x40, 0xa3, 0xd0, 0x98, 0x7c, + 0xc2, 0x24, 0x72, 0x95, 0xd9, 0x92, 0xdd, 0x68, 0x9b, 0x34, 0xde, 0xc1, 0x67, 0x72, 0xf8, 0x01, + 0x2d, 0x5c, 0x6f, 0xc7, 0xa1, 0x4f, 0x49, 0xa7, 0x04, 0x59, 0x94, 0xd6, 0xc1, 0xdb, 0x89, 0xaf, + 0xe8, 0x6b, 0xd2, 0x71, 0x1d, 0x26, 0x6a, 0x9d, 0xb6, 0xcf, 0xba, 0xe7, 0xcf, 0xd8, 0xde, 0xc4, + 0x6c, 0xf7, 0x7b, 0x97, 0x0f, 0xea, 0x9b, 0x13, 0x6f, 0x1f, 0xfc, 0x68, 0x91, 0xc7, 0x7b, 0x57, + 0xdc, 0xce, 0xe9, 0x7b, 0x72, 0x64, 0x6c, 0x36, 0x81, 0xf4, 0x9b, 0x83, 0x43, 0x9e, 0x7a, 0x76, + 0x78, 0x3f, 0xf6, 0x13, 0xd7, 0x7d, 0xe7, 0x9b, 0x9d, 0x62, 0xe8, 0x90, 0x3c, 0x52, 0xd2, 0x98, + 0x54, 0xe0, 0x4c, 0x5b, 0xa8, 0xdc, 0x33, 0x74, 0xcf, 0xfb, 0xff, 0xb0, 0xde, 0x4a, 0x63, 0x86, + 0x8d, 0xc3, 0xc3, 0xba, 0x6a, 0x77, 0x44, 0x3f, 0x91, 0x9e, 0x5b, 0x6d, 0x0e, 0x79, 0x2a, 0x50, + 0x29, 0x69, 0x53, 0xa9, 0xc7, 0x18, 0xb5, 0x1d, 0xec, 0x05, 0xdb, 0x2d, 0x89, 0xd5, 0x4b, 0x62, + 0xd7, 0xde, 0x3c, 0x74, 0xde, 0x1b, 0x3d, 0x46, 0x4f, 0xa5, 0xf0, 0xbf, 0x72, 0xb5, 0x58, 0xc7, + 0xe1, 0x72, 0x1d, 0x87, 0x7f, 0xd6, 0x71, 0xf8, 0x73, 0x13, 0x07, 0xcb, 0x4d, 0x1c, 0xfc, 0xda, + 0xc4, 0xc1, 0xc7, 0x97, 0x85, 0xb4, 0xe5, 0x6c, 0xc4, 0x04, 0x2a, 0x7e, 0x0b, 0x99, 0x7a, 0xf5, + 0xa6, 0x49, 0x8a, 0xc0, 0x0a, 0xf8, 0x7c, 0x1b, 0x18, 0x97, 0x88, 0x51, 0xc7, 0x45, 0xe2, 0xe2, + 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3a, 0x01, 0x99, 0x19, 0x92, 0x02, 0x00, 0x00, +} + +func (m *DenomPrice) 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 *DenomPrice) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DenomPrice) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.Price.Size() + i -= size + if _, err := m.Price.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintExtension(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Denom) > 0 { + i -= len(m.Denom) + copy(dAtA[i:], m.Denom) + i = encodeVarintExtension(dAtA, i, uint64(len(m.Denom))) + i-- + dAtA[i] = 0xa + } + 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 = encodeVarintExtension(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.Height != 0 { + i = encodeVarintExtension(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *VoteExtensionTx) 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 *VoteExtensionTx) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VoteExtensionTx) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.ExtendedCommitInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExtension(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.MissCounter.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExtension(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.StakeWeightedPrices) > 0 { + for iNdEx := len(m.StakeWeightedPrices) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.StakeWeightedPrices[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintExtension(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintExtension(dAtA []byte, offset int, v uint64) int { + offset -= sovExtension(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *DenomPrice) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Denom) + if l > 0 { + n += 1 + l + sovExtension(uint64(l)) + } + l = m.Price.Size() + n += 1 + l + sovExtension(uint64(l)) + return n +} + +func (m *VoteExtension) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Height != 0 { + n += 1 + sovExtension(uint64(m.Height)) + } + if len(m.Prices) > 0 { + for _, e := range m.Prices { + l = e.Size() + n += 1 + l + sovExtension(uint64(l)) + } + } + return n +} + +func (m *VoteExtensionTx) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.StakeWeightedPrices) > 0 { + for _, e := range m.StakeWeightedPrices { + l = e.Size() + n += 1 + l + sovExtension(uint64(l)) + } + } + l = m.MissCounter.Size() + n += 1 + l + sovExtension(uint64(l)) + l = m.ExtendedCommitInfo.Size() + n += 1 + l + sovExtension(uint64(l)) + return n +} + +func sovExtension(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozExtension(x uint64) (n int) { + return sovExtension(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *DenomPrice) 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 ErrIntOverflowExtension + } + 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: DenomPrice: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DenomPrice: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + 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 ErrIntOverflowExtension + } + 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 ErrInvalidLengthExtension + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthExtension + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Denom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Price", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExtension + } + 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 ErrInvalidLengthExtension + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthExtension + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Price.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExtension(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthExtension + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + 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 ErrIntOverflowExtension + } + 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 ErrIntOverflowExtension + } + 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 ErrIntOverflowExtension + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExtension + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExtension + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Prices = append(m.Prices, DenomPrice{}) + if err := m.Prices[len(m.Prices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExtension(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthExtension + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VoteExtensionTx) 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 ErrIntOverflowExtension + } + 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: VoteExtensionTx: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VoteExtensionTx: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StakeWeightedPrices", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExtension + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExtension + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExtension + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StakeWeightedPrices = append(m.StakeWeightedPrices, DenomPrice{}) + if err := m.StakeWeightedPrices[len(m.StakeWeightedPrices)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MissCounter", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExtension + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExtension + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExtension + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MissCounter.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ExtendedCommitInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowExtension + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthExtension + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthExtension + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.ExtendedCommitInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipExtension(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthExtension + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipExtension(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExtension + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExtension + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowExtension + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthExtension + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupExtension + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthExtension + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthExtension = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowExtension = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupExtension = fmt.Errorf("proto: unexpected end of group") +)